aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig65
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/amba-clcd.c7
-rw-r--r--drivers/video/atafb.c14
-rw-r--r--drivers/video/atmel_lcdfb.c20
-rw-r--r--drivers/video/aty/atyfb.h3
-rw-r--r--drivers/video/aty/atyfb_base.c960
-rw-r--r--drivers/video/aty/mach64_accel.c7
-rw-r--r--drivers/video/au1100fb.c7
-rw-r--r--drivers/video/backlight/Kconfig35
-rw-r--r--drivers/video/backlight/Makefile4
-rw-r--r--drivers/video/backlight/adp5520_bl.c377
-rw-r--r--drivers/video/backlight/adx_bl.c178
-rw-r--r--drivers/video/backlight/backlight.c42
-rw-r--r--drivers/video/backlight/corgi_lcd.c6
-rw-r--r--drivers/video/backlight/da903x_bl.c20
-rw-r--r--drivers/video/backlight/hp680_bl.c2
-rw-r--r--drivers/video/backlight/jornada720_bl.c2
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/backlight/lms283gf05.c242
-rw-r--r--drivers/video/backlight/ltv350qv.c1
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c36
-rw-r--r--drivers/video/backlight/pwm_bl.c2
-rw-r--r--drivers/video/backlight/tdo24m.c3
-rw-r--r--drivers/video/backlight/tosa_lcd.c2
-rw-r--r--drivers/video/backlight/vgg2432a4.c3
-rw-r--r--drivers/video/backlight/wm831x_bl.c250
-rw-r--r--drivers/video/cfbcopyarea.c2
-rw-r--r--drivers/video/cobalt_lcdfb.c2
-rw-r--r--drivers/video/console/.gitignore2
-rw-r--r--drivers/video/console/Kconfig9
-rw-r--r--drivers/video/console/Makefile12
-rw-r--r--drivers/video/console/bitblit.c8
-rw-r--r--drivers/video/console/fbcon.c69
-rw-r--r--drivers/video/console/fbcon_rotate.h2
-rw-r--r--drivers/video/console/newport_con.c2
-rw-r--r--drivers/video/console/prom.uni11
-rw-r--r--drivers/video/console/promcon.c598
-rw-r--r--drivers/video/console/sticore.c9
-rw-r--r--drivers/video/console/vgacon.c9
-rw-r--r--drivers/video/da8xx-fb.c889
-rw-r--r--drivers/video/ep93xx-fb.c646
-rw-r--r--drivers/video/fb_defio.c2
-rw-r--r--drivers/video/fbmem.c35
-rw-r--r--drivers/video/fbmon.c4
-rw-r--r--drivers/video/fsl-diu-fb.c20
-rw-r--r--drivers/video/hitfb.c66
-rw-r--r--drivers/video/i810/i810_main.c5
-rw-r--r--drivers/video/imxfb.c186
-rw-r--r--drivers/video/matrox/g450_pll.c209
-rw-r--r--drivers/video/matrox/g450_pll.h8
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c18
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c618
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.h4
-rw-r--r--drivers/video/matrox/matroxfb_Ti3026.c262
-rw-r--r--drivers/video/matrox/matroxfb_accel.c129
-rw-r--r--drivers/video/matrox/matroxfb_accel.h2
-rw-r--r--drivers/video/matrox/matroxfb_base.c770
-rw-r--r--drivers/video/matrox/matroxfb_base.h80
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c167
-rw-r--r--drivers/video/matrox/matroxfb_g450.c185
-rw-r--r--drivers/video/matrox/matroxfb_g450.h8
-rw-r--r--drivers/video/matrox/matroxfb_maven.c50
-rw-r--r--drivers/video/matrox/matroxfb_misc.c288
-rw-r--r--drivers/video/matrox/matroxfb_misc.h15
-rw-r--r--drivers/video/msm/Makefile19
-rw-r--r--drivers/video/msm/mddi.c827
-rw-r--r--drivers/video/msm/mddi_client_dummy.c97
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c256
-rw-r--r--drivers/video/msm/mddi_client_toshiba.c284
-rw-r--r--drivers/video/msm/mddi_hw.h305
-rw-r--r--drivers/video/msm/mdp.c520
-rw-r--r--drivers/video/msm/mdp_csc_table.h582
-rw-r--r--drivers/video/msm/mdp_hw.h621
-rw-r--r--drivers/video/msm/mdp_ppp.c730
-rw-r--r--drivers/video/msm/mdp_scale_tables.c766
-rw-r--r--drivers/video/msm/mdp_scale_tables.h38
-rw-r--r--drivers/video/msm/msm_fb.c636
-rw-r--r--drivers/video/mx3fb.c92
-rw-r--r--drivers/video/omap/Kconfig82
-rw-r--r--drivers/video/omap/Makefile12
-rw-r--r--drivers/video/omap/blizzard.c101
-rw-r--r--drivers/video/omap/dispc.c138
-rw-r--r--drivers/video/omap/dispc.h7
-rw-r--r--drivers/video/omap/hwa742.c2
-rw-r--r--drivers/video/omap/lcd_2430sdp.c202
-rw-r--r--drivers/video/omap/lcd_ams_delta.c137
-rw-r--r--drivers/video/omap/lcd_apollon.c138
-rw-r--r--drivers/video/omap/lcd_h3.c4
-rw-r--r--drivers/video/omap/lcd_h4.c4
-rw-r--r--drivers/video/omap/lcd_inn1510.c4
-rw-r--r--drivers/video/omap/lcd_inn1610.c4
-rw-r--r--drivers/video/omap/lcd_ldp.c200
-rw-r--r--drivers/video/omap/lcd_mipid.c625
-rw-r--r--drivers/video/omap/lcd_omap2evm.c191
-rw-r--r--drivers/video/omap/lcd_omap3beagle.c130
-rw-r--r--drivers/video/omap/lcd_omap3evm.c192
-rw-r--r--drivers/video/omap/lcd_osk.c4
-rw-r--r--drivers/video/omap/lcd_overo.c179
-rw-r--r--drivers/video/omap/lcd_palmte.c4
-rw-r--r--drivers/video/omap/lcd_palmtt.c4
-rw-r--r--drivers/video/omap/lcd_palmz71.c4
-rw-r--r--drivers/video/omap/omapfb_main.c100
-rw-r--r--drivers/video/omap/rfbi.c7
-rw-r--r--drivers/video/platinumfb.c14
-rw-r--r--drivers/video/ps3fb.c2
-rw-r--r--drivers/video/pxafb.c34
-rw-r--r--drivers/video/s3c-fb.c23
-rw-r--r--drivers/video/s3c2410fb.c6
-rw-r--r--drivers/video/sa1100fb.c2
-rw-r--r--drivers/video/savage/savagefb_driver.c20
-rw-r--r--drivers/video/sh7760fb.c19
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c384
-rw-r--r--drivers/video/sis/sis_main.c7
-rw-r--r--drivers/video/sis/vstruct.h2
-rw-r--r--drivers/video/sm501fb.c26
-rw-r--r--drivers/video/stifb.c7
-rw-r--r--drivers/video/tmiofb.c2
-rw-r--r--drivers/video/uvesafb.c34
-rw-r--r--drivers/video/via/accel.c589
-rw-r--r--drivers/video/via/accel.h13
-rw-r--r--drivers/video/via/chip.h4
-rw-r--r--drivers/video/via/dvi.c6
-rw-r--r--drivers/video/via/global.c3
-rw-r--r--drivers/video/via/global.h2
-rw-r--r--drivers/video/via/hw.c478
-rw-r--r--drivers/video/via/hw.h57
-rw-r--r--drivers/video/via/ioctl.h6
-rw-r--r--drivers/video/via/lcd.c31
-rw-r--r--drivers/video/via/share.h98
-rw-r--r--drivers/video/via/via_i2c.c64
-rw-r--r--drivers/video/via/viafbdev.c1064
-rw-r--r--drivers/video/via/viafbdev.h64
-rw-r--r--drivers/video/via/viamode.c100
-rw-r--r--drivers/video/via/viamode.h141
-rw-r--r--drivers/video/via/vt1636.c4
-rw-r--r--drivers/video/w100fb.c4
-rw-r--r--drivers/video/xen-fbfront.c8
138 files changed, 14803 insertions, 4457 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d6d65ef85f54..188e1ba3b69f 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -7,6 +7,8 @@ menu "Graphics support"
7 7
8source "drivers/char/agp/Kconfig" 8source "drivers/char/agp/Kconfig"
9 9
10source "drivers/gpu/vga/Kconfig"
11
10source "drivers/gpu/drm/Kconfig" 12source "drivers/gpu/drm/Kconfig"
11 13
12config VGASTATE 14config VGASTATE
@@ -616,6 +618,8 @@ config FB_STI
616 select FB_CFB_FILLRECT 618 select FB_CFB_FILLRECT
617 select FB_CFB_COPYAREA 619 select FB_CFB_COPYAREA
618 select FB_CFB_IMAGEBLIT 620 select FB_CFB_IMAGEBLIT
621 select STI_CONSOLE
622 select VT
619 default y 623 default y
620 ---help--- 624 ---help---
621 STI refers to the HP "Standard Text Interface" which is a set of 625 STI refers to the HP "Standard Text Interface" which is a set of
@@ -933,7 +937,7 @@ config FB_S1D13XXX
933 937
934config FB_ATMEL 938config FB_ATMEL
935 tristate "AT91/AT32 LCD Controller support" 939 tristate "AT91/AT32 LCD Controller support"
936 depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || AVR32) 940 depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9G10 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 || ARCH_AT91CAP9 || AVR32)
937 select FB_CFB_FILLRECT 941 select FB_CFB_FILLRECT
938 select FB_CFB_COPYAREA 942 select FB_CFB_COPYAREA
939 select FB_CFB_IMAGEBLIT 943 select FB_CFB_IMAGEBLIT
@@ -949,7 +953,7 @@ config FB_INTSRAM
949 953
950config FB_ATMEL_STN 954config FB_ATMEL_STN
951 bool "Use a STN display with AT91/AT32 LCD Controller" 955 bool "Use a STN display with AT91/AT32 LCD Controller"
952 depends on FB_ATMEL && MACH_AT91SAM9261EK 956 depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
953 default n 957 default n
954 help 958 help
955 Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD 959 Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
@@ -1117,12 +1121,13 @@ config FB_CARILLO_RANCH
1117 1121
1118config FB_INTEL 1122config FB_INTEL
1119 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)" 1123 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
1120 depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL 1124 depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EMBEDDED
1121 select FB_MODE_HELPERS 1125 select FB_MODE_HELPERS
1122 select FB_CFB_FILLRECT 1126 select FB_CFB_FILLRECT
1123 select FB_CFB_COPYAREA 1127 select FB_CFB_COPYAREA
1124 select FB_CFB_IMAGEBLIT 1128 select FB_CFB_IMAGEBLIT
1125 select FB_BOOT_VESA_SUPPORT if FB_INTEL = y 1129 select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
1130 depends on !DRM_I915
1126 help 1131 help
1127 This driver supports the on-board graphics built in to the Intel 1132 This driver supports the on-board graphics built in to the Intel
1128 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. 1133 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
@@ -1270,26 +1275,6 @@ config FB_MATROX_MAVEN
1270 painting procedures (the secondary head does not use acceleration 1275 painting procedures (the secondary head does not use acceleration
1271 engine). 1276 engine).
1272 1277
1273config FB_MATROX_MULTIHEAD
1274 bool "Multihead support"
1275 depends on FB_MATROX
1276 ---help---
1277 Say Y here if you have more than one (supported) Matrox device in
1278 your computer and you want to use all of them for different monitors
1279 ("multihead"). If you have only one device, you should say N because
1280 the driver compiled with Y is larger and a bit slower, especially on
1281 ia32 (ix86).
1282
1283 If you said M to "Matrox unified accelerated driver" and N here, you
1284 will still be able to use several Matrox devices simultaneously:
1285 insert several instances of the module matroxfb into the kernel
1286 with insmod, supplying the parameter "dev=N" where N is 0, 1, etc.
1287 for the different Matrox devices. This method is slightly faster but
1288 uses 40 KB of kernel memory per Matrox card.
1289
1290 There is no need for enabling 'Matrox multihead support' if you have
1291 only one Matrox card in the box.
1292
1293config FB_RADEON 1278config FB_RADEON
1294 tristate "ATI Radeon display support" 1279 tristate "ATI Radeon display support"
1295 depends on FB && PCI 1280 depends on FB && PCI
@@ -1864,7 +1849,7 @@ config FB_W100
1864 1849
1865config FB_SH_MOBILE_LCDC 1850config FB_SH_MOBILE_LCDC
1866 tristate "SuperH Mobile LCDC framebuffer support" 1851 tristate "SuperH Mobile LCDC framebuffer support"
1867 depends on FB && SUPERH 1852 depends on FB && SUPERH && HAVE_CLK
1868 select FB_SYS_FILLRECT 1853 select FB_SYS_FILLRECT
1869 select FB_SYS_COPYAREA 1854 select FB_SYS_COPYAREA
1870 select FB_SYS_IMAGEBLIT 1855 select FB_SYS_IMAGEBLIT
@@ -2036,6 +2021,17 @@ config FB_SH7760
2036 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for 2021 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
2037 panels <= 320 pixel horizontal resolution. 2022 panels <= 320 pixel horizontal resolution.
2038 2023
2024config FB_DA8XX
2025 tristate "DA8xx/OMAP-L1xx Framebuffer support"
2026 depends on FB && ARCH_DAVINCI_DA8XX
2027 select FB_CFB_FILLRECT
2028 select FB_CFB_COPYAREA
2029 select FB_CFB_IMAGEBLIT
2030 ---help---
2031 This is the frame buffer device driver for the TI LCD controller
2032 found on DA8xx/OMAP-L1xx SoCs.
2033 If unsure, say N.
2034
2039config FB_VIRTUAL 2035config FB_VIRTUAL
2040 tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" 2036 tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
2041 depends on FB 2037 depends on FB
@@ -2112,13 +2108,32 @@ config FB_MB862XX_LIME
2112 ---help--- 2108 ---help---
2113 Framebuffer support for Fujitsu Lime GDC on host CPU bus. 2109 Framebuffer support for Fujitsu Lime GDC on host CPU bus.
2114 2110
2111config FB_EP93XX
2112 tristate "EP93XX frame buffer support"
2113 depends on FB && ARCH_EP93XX
2114 select FB_CFB_FILLRECT
2115 select FB_CFB_COPYAREA
2116 select FB_CFB_IMAGEBLIT
2117 ---help---
2118 Framebuffer driver for the Cirrus Logic EP93XX series of processors.
2119 This driver is also available as a module. The module will be called
2120 ep93xx-fb.
2121
2115config FB_PRE_INIT_FB 2122config FB_PRE_INIT_FB
2116 bool "Don't reinitialize, use bootloader's GDC/Display configuration" 2123 bool "Don't reinitialize, use bootloader's GDC/Display configuration"
2117 depends on FB_MB862XX_LIME 2124 depends on FB && FB_MB862XX_LIME
2118 ---help--- 2125 ---help---
2119 Select this option if display contents should be inherited as set by 2126 Select this option if display contents should be inherited as set by
2120 the bootloader. 2127 the bootloader.
2121 2128
2129config FB_MSM
2130 tristate
2131 depends on FB && ARCH_MSM
2132 select FB_CFB_FILLRECT
2133 select FB_CFB_COPYAREA
2134 select FB_CFB_IMAGEBLIT
2135 default y
2136
2122config FB_MX3 2137config FB_MX3
2123 tristate "MX3 Framebuffer support" 2138 tristate "MX3 Framebuffer support"
2124 depends on FB && MX3_IPU 2139 depends on FB && MX3_IPU
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 01a819f47371..80232e124889 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_FB_Q40) += q40fb.o
85obj-$(CONFIG_FB_TGA) += tgafb.o 85obj-$(CONFIG_FB_TGA) += tgafb.o
86obj-$(CONFIG_FB_HP300) += hpfb.o 86obj-$(CONFIG_FB_HP300) += hpfb.o
87obj-$(CONFIG_FB_G364) += g364fb.o 87obj-$(CONFIG_FB_G364) += g364fb.o
88obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o
88obj-$(CONFIG_FB_SA1100) += sa1100fb.o 89obj-$(CONFIG_FB_SA1100) += sa1100fb.o
89obj-$(CONFIG_FB_HIT) += hitfb.o 90obj-$(CONFIG_FB_HIT) += hitfb.o
90obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o 91obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o
@@ -126,6 +127,7 @@ obj-$(CONFIG_FB_OMAP) += omap/
126obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o 127obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
127obj-$(CONFIG_FB_CARMINE) += carminefb.o 128obj-$(CONFIG_FB_CARMINE) += carminefb.o
128obj-$(CONFIG_FB_MB862XX) += mb862xx/ 129obj-$(CONFIG_FB_MB862XX) += mb862xx/
130obj-$(CONFIG_FB_MSM) += msm/
129 131
130# Platform or fallback drivers go here 132# Platform or fallback drivers go here
131obj-$(CONFIG_FB_UVESA) += uvesafb.o 133obj-$(CONFIG_FB_UVESA) += uvesafb.o
@@ -136,6 +138,7 @@ obj-$(CONFIG_FB_OF) += offb.o
136obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o 138obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
137obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o 139obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
138obj-$(CONFIG_FB_MX3) += mx3fb.o 140obj-$(CONFIG_FB_MX3) += mx3fb.o
141obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
139 142
140# the test framebuffer is last 143# the test framebuffer is last
141obj-$(CONFIG_FB_VIRTUAL) += vfb.o 144obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index fb8163d181ab..a21efcd10b78 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -226,9 +226,10 @@ static int clcdfb_set_par(struct fb_info *info)
226 clcdfb_enable(fb, regs.cntl); 226 clcdfb_enable(fb, regs.cntl);
227 227
228#ifdef DEBUG 228#ifdef DEBUG
229 printk(KERN_INFO "CLCD: Registers set to\n" 229 printk(KERN_INFO
230 KERN_INFO " %08x %08x %08x %08x\n" 230 "CLCD: Registers set to\n"
231 KERN_INFO " %08x %08x %08x %08x\n", 231 " %08x %08x %08x %08x\n"
232 " %08x %08x %08x %08x\n",
232 readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1), 233 readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
233 readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3), 234 readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
234 readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS), 235 readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 018850c116c6..37624f74e88b 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -329,12 +329,6 @@ extern unsigned char fontdata_8x16[];
329 * 329 *
330 * * perform fb specific mmap * 330 * * perform fb specific mmap *
331 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); 331 * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
332 *
333 * * save current hardware state *
334 * void (*fb_save_state)(struct fb_info *info);
335 *
336 * * restore saved state *
337 * void (*fb_restore_state)(struct fb_info *info);
338 * } ; 332 * } ;
339 */ 333 */
340 334
@@ -2405,6 +2399,9 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2405 return 0; 2399 return 0;
2406} 2400}
2407 2401
2402/* fbhw->encode_fix() must be called with fb_info->mm_lock held
2403 * if it is called after the register_framebuffer() - not a case here
2404 */
2408static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) 2405static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2409{ 2406{
2410 struct atafb_par par; 2407 struct atafb_par par;
@@ -2414,7 +2411,8 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
2414 if (err) 2411 if (err)
2415 return err; 2412 return err;
2416 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 2413 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2417 return fbhw->encode_fix(fix, &par); 2414 err = fbhw->encode_fix(fix, &par);
2415 return err;
2418} 2416}
2419 2417
2420static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) 2418static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -2743,7 +2741,9 @@ static int atafb_set_par(struct fb_info *info)
2743 2741
2744 /* Decode wanted screen parameters */ 2742 /* Decode wanted screen parameters */
2745 fbhw->decode_var(&info->var, par); 2743 fbhw->decode_var(&info->var, par);
2744 mutex_lock(&info->mm_lock);
2746 fbhw->encode_fix(&info->fix, par); 2745 fbhw->encode_fix(&info->fix, par);
2746 mutex_unlock(&info->mm_lock);
2747 2747
2748 /* Set new videomode */ 2748 /* Set new videomode */
2749 ata_set_par(par); 2749 ata_set_par(par);
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 5afd64482f55..d5e801076d33 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -182,7 +182,8 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
182{ 182{
183 unsigned long value; 183 unsigned long value;
184 184
185 if (!(cpu_is_at91sam9261() || cpu_is_at32ap7000())) 185 if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
186 || cpu_is_at32ap7000()))
186 return xres; 187 return xres;
187 188
188 value = xres; 189 value = xres;
@@ -261,6 +262,9 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
261/** 262/**
262 * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory 263 * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
263 * @sinfo: the frame buffer to allocate memory for 264 * @sinfo: the frame buffer to allocate memory for
265 *
266 * This function is called only from the atmel_lcdfb_probe()
267 * so no locking by fb_info->mm_lock around smem_len setting is needed.
264 */ 268 */
265static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) 269static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
266{ 270{
@@ -480,6 +484,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
480 unsigned long value; 484 unsigned long value;
481 unsigned long clk_value_khz; 485 unsigned long clk_value_khz;
482 unsigned long bits_per_line; 486 unsigned long bits_per_line;
487 unsigned long pix_factor = 2;
483 488
484 might_sleep(); 489 might_sleep();
485 490
@@ -512,20 +517,24 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
512 /* Now, the LCDC core... */ 517 /* Now, the LCDC core... */
513 518
514 /* Set pixel clock */ 519 /* Set pixel clock */
520 if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
521 pix_factor = 1;
522
515 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 523 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
516 524
517 value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock)); 525 value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock));
518 526
519 if (value < 2) { 527 if (value < pix_factor) {
520 dev_notice(info->device, "Bypassing pixel clock divider\n"); 528 dev_notice(info->device, "Bypassing pixel clock divider\n");
521 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); 529 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
522 } else { 530 } else {
523 value = (value / 2) - 1; 531 value = (value / pix_factor) - 1;
524 dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", 532 dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n",
525 value); 533 value);
526 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, 534 lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1,
527 value << ATMEL_LCDC_CLKVAL_OFFSET); 535 value << ATMEL_LCDC_CLKVAL_OFFSET);
528 info->var.pixclock = KHZ2PICOS(clk_value_khz / (2 * (value + 1))); 536 info->var.pixclock =
537 KHZ2PICOS(clk_value_khz / (pix_factor * (value + 1)));
529 dev_dbg(info->device, " updated pixclk: %lu KHz\n", 538 dev_dbg(info->device, " updated pixclk: %lu KHz\n",
530 PICOS2KHZ(info->var.pixclock)); 539 PICOS2KHZ(info->var.pixclock));
531 } 540 }
@@ -821,7 +830,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
821 info->fix = atmel_lcdfb_fix; 830 info->fix = atmel_lcdfb_fix;
822 831
823 /* Enable LCDC Clocks */ 832 /* Enable LCDC Clocks */
824 if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) { 833 if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()
834 || cpu_is_at32ap7000()) {
825 sinfo->bus_clk = clk_get(dev, "hck1"); 835 sinfo->bus_clk = clk_get(dev, "hck1");
826 if (IS_ERR(sinfo->bus_clk)) { 836 if (IS_ERR(sinfo->bus_clk)) {
827 ret = PTR_ERR(sinfo->bus_clk); 837 ret = PTR_ERR(sinfo->bus_clk);
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index 7691e73823d3..1f39a62f899b 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -187,6 +187,8 @@ struct atyfb_par {
187 int mtrr_reg; 187 int mtrr_reg;
188#endif 188#endif
189 u32 mem_cntl; 189 u32 mem_cntl;
190 struct crtc saved_crtc;
191 union aty_pll saved_pll;
190}; 192};
191 193
192 /* 194 /*
@@ -217,6 +219,7 @@ struct atyfb_par {
217#define M64F_XL_DLL 0x00080000 219#define M64F_XL_DLL 0x00080000
218#define M64F_MFB_FORCE_4 0x00100000 220#define M64F_MFB_FORCE_4 0x00100000
219#define M64F_HW_TRIPLE 0x00200000 221#define M64F_HW_TRIPLE 0x00200000
222#define M64F_XL_MEM 0x00400000
220 /* 223 /*
221 * Register access 224 * Register access
222 */ 225 */
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 1207c208a30b..913b4a47ae52 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -66,6 +66,8 @@
66#include <linux/spinlock.h> 66#include <linux/spinlock.h>
67#include <linux/wait.h> 67#include <linux/wait.h>
68#include <linux/backlight.h> 68#include <linux/backlight.h>
69#include <linux/reboot.h>
70#include <linux/dmi.h>
69 71
70#include <asm/io.h> 72#include <asm/io.h>
71#include <linux/uaccess.h> 73#include <linux/uaccess.h>
@@ -130,7 +132,7 @@
130#endif 132#endif
131 133
132#define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args) 134#define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)
133#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) 135#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
134 136
135#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ 137#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
136defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) 138defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
@@ -186,24 +188,23 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par)
186 */ 188 */
187static void ATIReduceRatio(int *Numerator, int *Denominator) 189static void ATIReduceRatio(int *Numerator, int *Denominator)
188{ 190{
189 int Multiplier, Divider, Remainder; 191 int Multiplier, Divider, Remainder;
190 192
191 Multiplier = *Numerator; 193 Multiplier = *Numerator;
192 Divider = *Denominator; 194 Divider = *Denominator;
193 195
194 while ((Remainder = Multiplier % Divider)) 196 while ((Remainder = Multiplier % Divider)) {
195 { 197 Multiplier = Divider;
196 Multiplier = Divider; 198 Divider = Remainder;
197 Divider = Remainder; 199 }
198 }
199 200
200 *Numerator /= Divider; 201 *Numerator /= Divider;
201 *Denominator /= Divider; 202 *Denominator /= Divider;
202} 203}
203#endif 204#endif
204 /* 205/*
205 * The Hardware parameters for each card 206 * The Hardware parameters for each card
206 */ 207 */
207 208
208struct pci_mmap_map { 209struct pci_mmap_map {
209 unsigned long voff; 210 unsigned long voff;
@@ -221,17 +222,19 @@ static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
221 .ypanstep = 1, 222 .ypanstep = 1,
222}; 223};
223 224
224 /* 225/*
225 * Frame buffer device API 226 * Frame buffer device API
226 */ 227 */
227 228
228static int atyfb_open(struct fb_info *info, int user); 229static int atyfb_open(struct fb_info *info, int user);
229static int atyfb_release(struct fb_info *info, int user); 230static int atyfb_release(struct fb_info *info, int user);
230static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); 231static int atyfb_check_var(struct fb_var_screeninfo *var,
232 struct fb_info *info);
231static int atyfb_set_par(struct fb_info *info); 233static int atyfb_set_par(struct fb_info *info);
232static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 234static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
233 u_int transp, struct fb_info *info); 235 u_int transp, struct fb_info *info);
234static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); 236static int atyfb_pan_display(struct fb_var_screeninfo *var,
237 struct fb_info *info);
235static int atyfb_blank(int blank, struct fb_info *info); 238static int atyfb_blank(int blank, struct fb_info *info);
236static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); 239static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
237#ifdef __sparc__ 240#ifdef __sparc__
@@ -239,9 +242,9 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
239#endif 242#endif
240static int atyfb_sync(struct fb_info *info); 243static int atyfb_sync(struct fb_info *info);
241 244
242 /* 245/*
243 * Internal routines 246 * Internal routines
244 */ 247 */
245 248
246static int aty_init(struct fb_info *info); 249static int aty_init(struct fb_info *info);
247 250
@@ -249,22 +252,25 @@ static int aty_init(struct fb_info *info);
249static int store_video_par(char *videopar, unsigned char m64_num); 252static int store_video_par(char *videopar, unsigned char m64_num);
250#endif 253#endif
251 254
252static struct crtc saved_crtc;
253static union aty_pll saved_pll;
254static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); 255static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
255 256
256static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); 257static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
257static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc); 258static int aty_var_to_crtc(const struct fb_info *info,
258static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var); 259 const struct fb_var_screeninfo *var,
260 struct crtc *crtc);
261static int aty_crtc_to_var(const struct crtc *crtc,
262 struct fb_var_screeninfo *var);
259static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info); 263static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
260#ifdef CONFIG_PPC 264#ifdef CONFIG_PPC
261static int read_aty_sense(const struct atyfb_par *par); 265static int read_aty_sense(const struct atyfb_par *par);
262#endif 266#endif
263 267
268static DEFINE_MUTEX(reboot_lock);
269static struct fb_info *reboot_info;
264 270
265 /* 271/*
266 * Interface used by the world 272 * Interface used by the world
267 */ 273 */
268 274
269static struct fb_var_screeninfo default_var = { 275static struct fb_var_screeninfo default_var = {
270 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 276 /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
@@ -361,8 +367,8 @@ static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };
361#define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) 367#define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
362#define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D) 368#define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
363 369
364#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4) 370#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM)
365#define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS) 371#define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS)
366 372
367static struct { 373static struct {
368 u16 pci_id; 374 u16 pci_id;
@@ -450,14 +456,14 @@ static int __devinit correct_chipset(struct atyfb_par *par)
450 type = chip_id & CFG_CHIP_TYPE; 456 type = chip_id & CFG_CHIP_TYPE;
451 rev = (chip_id & CFG_CHIP_REV) >> 24; 457 rev = (chip_id & CFG_CHIP_REV) >> 24;
452 458
453 switch(par->pci_id) { 459 switch (par->pci_id) {
454#ifdef CONFIG_FB_ATY_GX 460#ifdef CONFIG_FB_ATY_GX
455 case PCI_CHIP_MACH64GX: 461 case PCI_CHIP_MACH64GX:
456 if(type != 0x00d7) 462 if (type != 0x00d7)
457 return -ENODEV; 463 return -ENODEV;
458 break; 464 break;
459 case PCI_CHIP_MACH64CX: 465 case PCI_CHIP_MACH64CX:
460 if(type != 0x0057) 466 if (type != 0x0057)
461 return -ENODEV; 467 return -ENODEV;
462 break; 468 break;
463#endif 469#endif
@@ -539,6 +545,7 @@ static char ram_edo[] __devinitdata = "EDO";
539static char ram_sdram[] __devinitdata = "SDRAM (1:1)"; 545static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
540static char ram_sgram[] __devinitdata = "SGRAM (1:1)"; 546static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
541static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)"; 547static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
548static char ram_wram[] __devinitdata = "WRAM";
542static char ram_off[] __devinitdata = "OFF"; 549static char ram_off[] __devinitdata = "OFF";
543#endif /* CONFIG_FB_ATY_CT */ 550#endif /* CONFIG_FB_ATY_CT */
544 551
@@ -553,11 +560,16 @@ static char *aty_gx_ram[8] __devinitdata = {
553#ifdef CONFIG_FB_ATY_CT 560#ifdef CONFIG_FB_ATY_CT
554static char *aty_ct_ram[8] __devinitdata = { 561static char *aty_ct_ram[8] __devinitdata = {
555 ram_off, ram_dram, ram_edo, ram_edo, 562 ram_off, ram_dram, ram_edo, ram_edo,
563 ram_sdram, ram_sgram, ram_wram, ram_resv
564};
565static char *aty_xl_ram[8] __devinitdata = {
566 ram_off, ram_dram, ram_edo, ram_edo,
556 ram_sdram, ram_sgram, ram_sdram32, ram_resv 567 ram_sdram, ram_sgram, ram_sdram32, ram_resv
557}; 568};
558#endif /* CONFIG_FB_ATY_CT */ 569#endif /* CONFIG_FB_ATY_CT */
559 570
560static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par) 571static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var,
572 struct atyfb_par *par)
561{ 573{
562 u32 pixclock = var->pixclock; 574 u32 pixclock = var->pixclock;
563#ifdef CONFIG_FB_ATY_GENERIC_LCD 575#ifdef CONFIG_FB_ATY_GENERIC_LCD
@@ -565,7 +577,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *p
565 par->pll.ct.xres = 0; 577 par->pll.ct.xres = 0;
566 if (par->lcd_table != 0) { 578 if (par->lcd_table != 0) {
567 lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par); 579 lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
568 if(lcd_on_off & LCD_ON) { 580 if (lcd_on_off & LCD_ON) {
569 par->pll.ct.xres = var->xres; 581 par->pll.ct.xres = var->xres;
570 pixclock = par->lcd_pixclock; 582 pixclock = par->lcd_pixclock;
571 } 583 }
@@ -577,7 +589,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *p
577#if defined(CONFIG_PPC) 589#if defined(CONFIG_PPC)
578 590
579/* 591/*
580 * Apple monitor sense 592 * Apple monitor sense
581 */ 593 */
582 594
583static int __devinit read_aty_sense(const struct atyfb_par *par) 595static int __devinit read_aty_sense(const struct atyfb_par *par)
@@ -618,16 +630,16 @@ static int __devinit read_aty_sense(const struct atyfb_par *par)
618/* ------------------------------------------------------------------------- */ 630/* ------------------------------------------------------------------------- */
619 631
620/* 632/*
621 * CRTC programming 633 * CRTC programming
622 */ 634 */
623 635
624static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) 636static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
625{ 637{
626#ifdef CONFIG_FB_ATY_GENERIC_LCD 638#ifdef CONFIG_FB_ATY_GENERIC_LCD
627 if (par->lcd_table != 0) { 639 if (par->lcd_table != 0) {
628 if(!M64_HAS(LT_LCD_REGS)) { 640 if (!M64_HAS(LT_LCD_REGS)) {
629 crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); 641 crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
630 aty_st_le32(LCD_INDEX, crtc->lcd_index, par); 642 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
631 } 643 }
632 crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par); 644 crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);
633 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); 645 crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
@@ -635,7 +647,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
635 647
636 /* switch to non shadow registers */ 648 /* switch to non shadow registers */
637 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & 649 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
638 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); 650 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
639 651
640 /* save stretching */ 652 /* save stretching */
641 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par); 653 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
@@ -656,7 +668,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
656 if (par->lcd_table != 0) { 668 if (par->lcd_table != 0) {
657 /* switch to shadow registers */ 669 /* switch to shadow registers */
658 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | 670 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
659 SHADOW_EN | SHADOW_RW_EN, par); 671 SHADOW_EN | SHADOW_RW_EN, par);
660 672
661 crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par); 673 crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
662 crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par); 674 crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
@@ -673,21 +685,20 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
673#ifdef CONFIG_FB_ATY_GENERIC_LCD 685#ifdef CONFIG_FB_ATY_GENERIC_LCD
674 if (par->lcd_table != 0) { 686 if (par->lcd_table != 0) {
675 /* stop CRTC */ 687 /* stop CRTC */
676 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); 688 aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl &
689 ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
677 690
678 /* update non-shadow registers first */ 691 /* update non-shadow registers first */
679 aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par); 692 aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);
680 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & 693 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
681 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); 694 ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
682 695
683 /* temporarily disable stretching */ 696 /* temporarily disable stretching */
684 aty_st_lcd(HORZ_STRETCHING, 697 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching &
685 crtc->horz_stretching & 698 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
686 ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par); 699 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching &
687 aty_st_lcd(VERT_STRETCHING, 700 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
688 crtc->vert_stretching & 701 VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
689 ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
690 VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
691 } 702 }
692#endif 703#endif
693 /* turn off CRT */ 704 /* turn off CRT */
@@ -695,17 +706,19 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
695 706
696 DPRINTK("setting up CRTC\n"); 707 DPRINTK("setting up CRTC\n");
697 DPRINTK("set primary CRT to %ix%i %c%c composite %c\n", 708 DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
698 ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1), 709 ((((crtc->h_tot_disp >> 16) & 0xff) + 1) << 3),
699 (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P', 710 (((crtc->v_tot_disp >> 16) & 0x7ff) + 1),
700 (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N'); 711 (crtc->h_sync_strt_wid & 0x200000) ? 'N' : 'P',
701 712 (crtc->v_sync_strt_wid & 0x200000) ? 'N' : 'P',
702 DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp); 713 (crtc->gen_cntl & CRTC_CSYNC_EN) ? 'P' : 'N');
703 DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid); 714
704 DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp); 715 DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc->h_tot_disp);
705 DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid); 716 DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc->h_sync_strt_wid);
717 DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc->v_tot_disp);
718 DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc->v_sync_strt_wid);
706 DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch); 719 DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
707 DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline); 720 DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
708 DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl); 721 DPRINTK("CRTC_GEN_CNTL: %x\n", crtc->gen_cntl);
709 722
710 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par); 723 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
711 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par); 724 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
@@ -725,16 +738,22 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
725 if (par->lcd_table != 0) { 738 if (par->lcd_table != 0) {
726 /* switch to shadow registers */ 739 /* switch to shadow registers */
727 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | 740 aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
728 (SHADOW_EN | SHADOW_RW_EN), par); 741 SHADOW_EN | SHADOW_RW_EN, par);
729 742
730 DPRINTK("set shadow CRT to %ix%i %c%c\n", 743 DPRINTK("set shadow CRT to %ix%i %c%c\n",
731 ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1), 744 ((((crtc->shadow_h_tot_disp >> 16) & 0xff) + 1) << 3),
732 (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P'); 745 (((crtc->shadow_v_tot_disp >> 16) & 0x7ff) + 1),
733 746 (crtc->shadow_h_sync_strt_wid & 0x200000) ? 'N' : 'P',
734 DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp); 747 (crtc->shadow_v_sync_strt_wid & 0x200000) ? 'N' : 'P');
735 DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid); 748
736 DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp); 749 DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n",
737 DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid); 750 crtc->shadow_h_tot_disp);
751 DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n",
752 crtc->shadow_h_sync_strt_wid);
753 DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n",
754 crtc->shadow_v_tot_disp);
755 DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n",
756 crtc->shadow_v_sync_strt_wid);
738 757
739 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par); 758 aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
740 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par); 759 aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
@@ -745,23 +764,35 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
745 DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl); 764 DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
746 DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching); 765 DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
747 DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching); 766 DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
748 if(!M64_HAS(LT_LCD_REGS)) 767 if (!M64_HAS(LT_LCD_REGS))
749 DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch); 768 DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
750 769
751 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par); 770 aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
752 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par); 771 aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
753 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par); 772 aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
754 if(!M64_HAS(LT_LCD_REGS)) { 773 if (!M64_HAS(LT_LCD_REGS)) {
755 aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par); 774 aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
756 aty_ld_le32(LCD_INDEX, par); 775 aty_ld_le32(LCD_INDEX, par);
757 aty_st_le32(LCD_INDEX, crtc->lcd_index, par); 776 aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
758 } 777 }
759 } 778 }
760#endif /* CONFIG_FB_ATY_GENERIC_LCD */ 779#endif /* CONFIG_FB_ATY_GENERIC_LCD */
761} 780}
762 781
782static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp)
783{
784 u32 line_length = vxres * bpp / 8;
785
786 if (par->ram_type == SGRAM ||
787 (!M64_HAS(XL_MEM) && par->ram_type == WRAM))
788 line_length = (line_length + 63) & ~63;
789
790 return line_length;
791}
792
763static int aty_var_to_crtc(const struct fb_info *info, 793static int aty_var_to_crtc(const struct fb_info *info,
764 const struct fb_var_screeninfo *var, struct crtc *crtc) 794 const struct fb_var_screeninfo *var,
795 struct crtc *crtc)
765{ 796{
766 struct atyfb_par *par = (struct atyfb_par *) info->par; 797 struct atyfb_par *par = (struct atyfb_par *) info->par;
767 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; 798 u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
@@ -769,13 +800,14 @@ static int aty_var_to_crtc(const struct fb_info *info,
769 u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol; 800 u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
770 u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync; 801 u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
771 u32 pix_width, dp_pix_width, dp_chain_mask; 802 u32 pix_width, dp_pix_width, dp_chain_mask;
803 u32 line_length;
772 804
773 /* input */ 805 /* input */
774 xres = var->xres; 806 xres = (var->xres + 7) & ~7;
775 yres = var->yres; 807 yres = var->yres;
776 vxres = var->xres_virtual; 808 vxres = (var->xres_virtual + 7) & ~7;
777 vyres = var->yres_virtual; 809 vyres = var->yres_virtual;
778 xoffset = var->xoffset; 810 xoffset = (var->xoffset + 7) & ~7;
779 yoffset = var->yoffset; 811 yoffset = var->yoffset;
780 bpp = var->bits_per_pixel; 812 bpp = var->bits_per_pixel;
781 if (bpp == 16) 813 if (bpp == 16)
@@ -795,47 +827,47 @@ static int aty_var_to_crtc(const struct fb_info *info,
795 if (bpp <= 8) { 827 if (bpp <= 8) {
796 bpp = 8; 828 bpp = 8;
797 pix_width = CRTC_PIX_WIDTH_8BPP; 829 pix_width = CRTC_PIX_WIDTH_8BPP;
798 dp_pix_width = 830 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
799 HOST_8BPP | SRC_8BPP | DST_8BPP | 831 BYTE_ORDER_LSB_TO_MSB;
800 BYTE_ORDER_LSB_TO_MSB;
801 dp_chain_mask = DP_CHAIN_8BPP; 832 dp_chain_mask = DP_CHAIN_8BPP;
802 } else if (bpp <= 15) { 833 } else if (bpp <= 15) {
803 bpp = 16; 834 bpp = 16;
804 pix_width = CRTC_PIX_WIDTH_15BPP; 835 pix_width = CRTC_PIX_WIDTH_15BPP;
805 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | 836 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
806 BYTE_ORDER_LSB_TO_MSB; 837 BYTE_ORDER_LSB_TO_MSB;
807 dp_chain_mask = DP_CHAIN_15BPP; 838 dp_chain_mask = DP_CHAIN_15BPP;
808 } else if (bpp <= 16) { 839 } else if (bpp <= 16) {
809 bpp = 16; 840 bpp = 16;
810 pix_width = CRTC_PIX_WIDTH_16BPP; 841 pix_width = CRTC_PIX_WIDTH_16BPP;
811 dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP | 842 dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
812 BYTE_ORDER_LSB_TO_MSB; 843 BYTE_ORDER_LSB_TO_MSB;
813 dp_chain_mask = DP_CHAIN_16BPP; 844 dp_chain_mask = DP_CHAIN_16BPP;
814 } else if (bpp <= 24 && M64_HAS(INTEGRATED)) { 845 } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
815 bpp = 24; 846 bpp = 24;
816 pix_width = CRTC_PIX_WIDTH_24BPP; 847 pix_width = CRTC_PIX_WIDTH_24BPP;
817 dp_pix_width = 848 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP |
818 HOST_8BPP | SRC_8BPP | DST_8BPP | 849 BYTE_ORDER_LSB_TO_MSB;
819 BYTE_ORDER_LSB_TO_MSB;
820 dp_chain_mask = DP_CHAIN_24BPP; 850 dp_chain_mask = DP_CHAIN_24BPP;
821 } else if (bpp <= 32) { 851 } else if (bpp <= 32) {
822 bpp = 32; 852 bpp = 32;
823 pix_width = CRTC_PIX_WIDTH_32BPP; 853 pix_width = CRTC_PIX_WIDTH_32BPP;
824 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | 854 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
825 BYTE_ORDER_LSB_TO_MSB; 855 BYTE_ORDER_LSB_TO_MSB;
826 dp_chain_mask = DP_CHAIN_32BPP; 856 dp_chain_mask = DP_CHAIN_32BPP;
827 } else 857 } else
828 FAIL("invalid bpp"); 858 FAIL("invalid bpp");
829 859
830 if (vxres * vyres * bpp / 8 > info->fix.smem_len) 860 line_length = calc_line_length(par, vxres, bpp);
861
862 if (vyres * line_length > info->fix.smem_len)
831 FAIL("not enough video RAM"); 863 FAIL("not enough video RAM");
832 864
833 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; 865 h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
834 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; 866 v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
835 867
836 if((xres > 1600) || (yres > 1200)) { 868 if ((xres > 1600) || (yres > 1200)) {
837 FAIL("MACH64 chips are designed for max 1600x1200\n" 869 FAIL("MACH64 chips are designed for max 1600x1200\n"
838 "select anoter resolution."); 870 "select anoter resolution.");
839 } 871 }
840 h_sync_strt = h_disp + var->right_margin; 872 h_sync_strt = h_disp + var->right_margin;
841 h_sync_end = h_sync_strt + var->hsync_len; 873 h_sync_end = h_sync_strt + var->hsync_len;
@@ -848,11 +880,12 @@ static int aty_var_to_crtc(const struct fb_info *info,
848 880
849#ifdef CONFIG_FB_ATY_GENERIC_LCD 881#ifdef CONFIG_FB_ATY_GENERIC_LCD
850 if (par->lcd_table != 0) { 882 if (par->lcd_table != 0) {
851 if(!M64_HAS(LT_LCD_REGS)) { 883 if (!M64_HAS(LT_LCD_REGS)) {
852 u32 lcd_index = aty_ld_le32(LCD_INDEX, par); 884 u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
853 crtc->lcd_index = lcd_index & 885 crtc->lcd_index = lcd_index &
854 ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS); 886 ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS |
855 aty_st_le32(LCD_INDEX, lcd_index, par); 887 LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
888 aty_st_le32(LCD_INDEX, lcd_index, par);
856 } 889 }
857 890
858 if (!M64_HAS(MOBIL_BUS)) 891 if (!M64_HAS(MOBIL_BUS))
@@ -867,12 +900,14 @@ static int aty_var_to_crtc(const struct fb_info *info,
867 USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); 900 USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
868 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT; 901 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
869 902
870 if((crtc->lcd_gen_cntl & LCD_ON) && 903 if ((crtc->lcd_gen_cntl & LCD_ON) &&
871 ((xres > par->lcd_width) || (yres > par->lcd_height))) { 904 ((xres > par->lcd_width) || (yres > par->lcd_height))) {
872 /* We cannot display the mode on the LCD. If the CRT is enabled 905 /*
873 we can turn off the LCD. 906 * We cannot display the mode on the LCD. If the CRT is
874 If the CRT is off, it isn't a good idea to switch it on; we don't 907 * enabled we can turn off the LCD.
875 know if one is connected. So it's better to fail then. 908 * If the CRT is off, it isn't a good idea to switch it
909 * on; we don't know if one is connected. So it's better
910 * to fail then.
876 */ 911 */
877 if (crtc->lcd_gen_cntl & CRT_ON) { 912 if (crtc->lcd_gen_cntl & CRT_ON) {
878 if (!(var->activate & FB_ACTIVATE_TEST)) 913 if (!(var->activate & FB_ACTIVATE_TEST))
@@ -895,17 +930,18 @@ static int aty_var_to_crtc(const struct fb_info *info,
895 930
896 vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED); 931 vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
897 932
898 /* This is horror! When we simulate, say 640x480 on an 800x600 933 /*
899 LCD monitor, the CRTC should be programmed 800x600 values for 934 * This is horror! When we simulate, say 640x480 on an 800x600
900 the non visible part, but 640x480 for the visible part. 935 * LCD monitor, the CRTC should be programmed 800x600 values for
901 This code has been tested on a laptop with it's 1400x1050 LCD 936 * the non visible part, but 640x480 for the visible part.
902 monitor and a conventional monitor both switched on. 937 * This code has been tested on a laptop with it's 1400x1050 LCD
903 Tested modes: 1280x1024, 1152x864, 1024x768, 800x600, 938 * monitor and a conventional monitor both switched on.
904 works with little glitches also with DOUBLESCAN modes 939 * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
940 * works with little glitches also with DOUBLESCAN modes
905 */ 941 */
906 if (yres < par->lcd_height) { 942 if (yres < par->lcd_height) {
907 VScan = par->lcd_height / yres; 943 VScan = par->lcd_height / yres;
908 if(VScan > 1) { 944 if (VScan > 1) {
909 VScan = 2; 945 VScan = 2;
910 vmode |= FB_VMODE_DOUBLE; 946 vmode |= FB_VMODE_DOUBLE;
911 } 947 }
@@ -931,7 +967,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
931 FAIL_MAX("h_disp too large", h_disp, 0xff); 967 FAIL_MAX("h_disp too large", h_disp, 0xff);
932 FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff); 968 FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
933 /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/ 969 /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
934 if(h_sync_wid > 0x1f) 970 if (h_sync_wid > 0x1f)
935 h_sync_wid = 0x1f; 971 h_sync_wid = 0x1f;
936 FAIL_MAX("h_total too large", h_total, 0x1ff); 972 FAIL_MAX("h_total too large", h_total, 0x1ff);
937 973
@@ -957,7 +993,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
957 FAIL_MAX("v_disp too large", v_disp, 0x7ff); 993 FAIL_MAX("v_disp too large", v_disp, 0x7ff);
958 FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff); 994 FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
959 /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/ 995 /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
960 if(v_sync_wid > 0x1f) 996 if (v_sync_wid > 0x1f)
961 v_sync_wid = 0x1f; 997 v_sync_wid = 0x1f;
962 FAIL_MAX("v_total too large", v_total, 0x7ff); 998 FAIL_MAX("v_total too large", v_total, 0x7ff);
963 999
@@ -969,14 +1005,18 @@ static int aty_var_to_crtc(const struct fb_info *info,
969 crtc->xoffset = xoffset; 1005 crtc->xoffset = xoffset;
970 crtc->yoffset = yoffset; 1006 crtc->yoffset = yoffset;
971 crtc->bpp = bpp; 1007 crtc->bpp = bpp;
972 crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); 1008 crtc->off_pitch =
1009 ((yoffset * line_length + xoffset * bpp / 8) / 8) |
1010 ((line_length / bpp) << 22);
973 crtc->vline_crnt_vline = 0; 1011 crtc->vline_crnt_vline = 0;
974 1012
975 crtc->h_tot_disp = h_total | (h_disp<<16); 1013 crtc->h_tot_disp = h_total | (h_disp << 16);
976 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) | 1014 crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |
977 ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21); 1015 ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |
978 crtc->v_tot_disp = v_total | (v_disp<<16); 1016 (h_sync_pol << 21);
979 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21); 1017 crtc->v_tot_disp = v_total | (v_disp << 16);
1018 crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
1019 (v_sync_pol << 21);
980 1020
981 /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */ 1021 /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
982 crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync; 1022 crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
@@ -991,13 +1031,15 @@ static int aty_var_to_crtc(const struct fb_info *info,
991#ifdef CONFIG_FB_ATY_GENERIC_LCD 1031#ifdef CONFIG_FB_ATY_GENERIC_LCD
992 if (par->lcd_table != 0) { 1032 if (par->lcd_table != 0) {
993 vdisplay = yres; 1033 vdisplay = yres;
994 if(vmode & FB_VMODE_DOUBLE) 1034 if (vmode & FB_VMODE_DOUBLE)
995 vdisplay <<= 1; 1035 vdisplay <<= 1;
996 crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH); 1036 crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
997 crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | 1037 crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
998 /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/ 1038 /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
999 USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); 1039 USE_SHADOWED_VEND |
1000 crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/); 1040 USE_SHADOWED_ROWCUR |
1041 SHADOW_EN | SHADOW_RW_EN);
1042 crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR/* | LOCK_8DOT*/;
1001 1043
1002 /* MOBILITY M1 tested, FIXME: LT */ 1044 /* MOBILITY M1 tested, FIXME: LT */
1003 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par); 1045 crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
@@ -1005,28 +1047,32 @@ static int aty_var_to_crtc(const struct fb_info *info,
1005 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) & 1047 crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
1006 ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3); 1048 ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
1007 1049
1008 crtc->horz_stretching &= 1050 crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO |
1009 ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | 1051 HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
1010 HORZ_STRETCH_MODE | HORZ_STRETCH_EN); 1052 HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
1011 if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) { 1053 if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
1012 do { 1054 do {
1013 /* 1055 /*
1014 * The horizontal blender misbehaves when HDisplay is less than a 1056 * The horizontal blender misbehaves when
1015 * a certain threshold (440 for a 1024-wide panel). It doesn't 1057 * HDisplay is less than a certain threshold
1016 * stretch such modes enough. Use pixel replication instead of 1058 * (440 for a 1024-wide panel). It doesn't
1017 * blending to stretch modes that can be made to exactly fit the 1059 * stretch such modes enough. Use pixel
1018 * panel width. The undocumented "NoLCDBlend" option allows the 1060 * replication instead of blending to stretch
1019 * pixel-replicated mode to be slightly wider or narrower than the 1061 * modes that can be made to exactly fit the
1020 * panel width. It also causes a mode that is exactly half as wide 1062 * panel width. The undocumented "NoLCDBlend"
1021 * as the panel to be pixel-replicated, rather than blended. 1063 * option allows the pixel-replicated mode to
1022 */ 1064 * be slightly wider or narrower than the
1065 * panel width. It also causes a mode that is
1066 * exactly half as wide as the panel to be
1067 * pixel-replicated, rather than blended.
1068 */
1023 int HDisplay = xres & ~7; 1069 int HDisplay = xres & ~7;
1024 int nStretch = par->lcd_width / HDisplay; 1070 int nStretch = par->lcd_width / HDisplay;
1025 int Remainder = par->lcd_width % HDisplay; 1071 int Remainder = par->lcd_width % HDisplay;
1026 1072
1027 if ((!Remainder && ((nStretch > 2))) || 1073 if ((!Remainder && ((nStretch > 2))) ||
1028 (((HDisplay * 16) / par->lcd_width) < 7)) { 1074 (((HDisplay * 16) / par->lcd_width) < 7)) {
1029 static const char StretchLoops[] = {10, 12, 13, 15, 16}; 1075 static const char StretchLoops[] = { 10, 12, 13, 15, 16 };
1030 int horz_stretch_loop = -1, BestRemainder; 1076 int horz_stretch_loop = -1, BestRemainder;
1031 int Numerator = HDisplay, Denominator = par->lcd_width; 1077 int Numerator = HDisplay, Denominator = par->lcd_width;
1032 int Index = 5; 1078 int Index = 5;
@@ -1075,12 +1121,12 @@ static int aty_var_to_crtc(const struct fb_info *info,
1075 (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0)); 1121 (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
1076 1122
1077 if (!M64_HAS(LT_LCD_REGS) && 1123 if (!M64_HAS(LT_LCD_REGS) &&
1078 xres <= (M64_HAS(MOBIL_BUS)?1024:800)) 1124 xres <= (M64_HAS(MOBIL_BUS) ? 1024 : 800))
1079 crtc->ext_vert_stretch |= VERT_STRETCH_MODE; 1125 crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
1080 } else { 1126 } else {
1081 /* 1127 /*
1082 * Don't use vertical blending if the mode is too wide or not 1128 * Don't use vertical blending if the mode is too wide
1083 * vertically stretched. 1129 * or not vertically stretched.
1084 */ 1130 */
1085 crtc->vert_stretching = 0; 1131 crtc->vert_stretching = 0;
1086 } 1132 }
@@ -1102,11 +1148,11 @@ static int aty_var_to_crtc(const struct fb_info *info,
1102 return 0; 1148 return 0;
1103} 1149}
1104 1150
1105static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var) 1151static int aty_crtc_to_var(const struct crtc *crtc,
1152 struct fb_var_screeninfo *var)
1106{ 1153{
1107 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync; 1154 u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1108 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, 1155 u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
1109 h_sync_pol;
1110 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; 1156 u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1111 u32 pix_width; 1157 u32 pix_width;
1112 u32 double_scan, interlace; 1158 u32 double_scan, interlace;
@@ -1138,8 +1184,8 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va
1138 lower = v_sync_strt - v_disp; 1184 lower = v_sync_strt - v_disp;
1139 vslen = v_sync_wid; 1185 vslen = v_sync_wid;
1140 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | 1186 sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1141 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | 1187 (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1142 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); 1188 (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1143 1189
1144 switch (pix_width) { 1190 switch (pix_width) {
1145#if 0 1191#if 0
@@ -1229,20 +1275,21 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va
1229 var->vsync_len = vslen; 1275 var->vsync_len = vslen;
1230 var->sync = sync; 1276 var->sync = sync;
1231 var->vmode = FB_VMODE_NONINTERLACED; 1277 var->vmode = FB_VMODE_NONINTERLACED;
1232 /* In double scan mode, the vertical parameters are doubled, so we need to 1278 /*
1233 half them to get the right values. 1279 * In double scan mode, the vertical parameters are doubled,
1234 In interlaced mode the values are already correct, so no correction is 1280 * so we need to halve them to get the right values.
1235 necessary. 1281 * In interlaced mode the values are already correct,
1282 * so no correction is necessary.
1236 */ 1283 */
1237 if (interlace) 1284 if (interlace)
1238 var->vmode = FB_VMODE_INTERLACED; 1285 var->vmode = FB_VMODE_INTERLACED;
1239 1286
1240 if (double_scan) { 1287 if (double_scan) {
1241 var->vmode = FB_VMODE_DOUBLE; 1288 var->vmode = FB_VMODE_DOUBLE;
1242 var->yres>>=1; 1289 var->yres >>= 1;
1243 var->upper_margin>>=1; 1290 var->upper_margin >>= 1;
1244 var->lower_margin>>=1; 1291 var->lower_margin >>= 1;
1245 var->vsync_len>>=1; 1292 var->vsync_len >>= 1;
1246 } 1293 }
1247 1294
1248 return 0; 1295 return 0;
@@ -1263,7 +1310,8 @@ static int atyfb_set_par(struct fb_info *info)
1263 if (par->asleep) 1310 if (par->asleep)
1264 return 0; 1311 return 0;
1265 1312
1266 if ((err = aty_var_to_crtc(info, var, &par->crtc))) 1313 err = aty_var_to_crtc(info, var, &par->crtc);
1314 if (err)
1267 return err; 1315 return err;
1268 1316
1269 pixclock = atyfb_get_pixclock(var, par); 1317 pixclock = atyfb_get_pixclock(var, par);
@@ -1272,7 +1320,9 @@ static int atyfb_set_par(struct fb_info *info)
1272 PRINTKE("Invalid pixclock\n"); 1320 PRINTKE("Invalid pixclock\n");
1273 return -EINVAL; 1321 return -EINVAL;
1274 } else { 1322 } else {
1275 if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll))) 1323 err = par->pll_ops->var_to_pll(info, pixclock,
1324 var->bits_per_pixel, &par->pll);
1325 if (err)
1276 return err; 1326 return err;
1277 } 1327 }
1278 1328
@@ -1290,22 +1340,23 @@ static int atyfb_set_par(struct fb_info *info)
1290 wait_for_idle(par); 1340 wait_for_idle(par);
1291 1341
1292 aty_set_crtc(par, &par->crtc); 1342 aty_set_crtc(par, &par->crtc);
1293 par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags); 1343 par->dac_ops->set_dac(info, &par->pll,
1344 var->bits_per_pixel, par->accel_flags);
1294 par->pll_ops->set_pll(info, &par->pll); 1345 par->pll_ops->set_pll(info, &par->pll);
1295 1346
1296#ifdef DEBUG 1347#ifdef DEBUG
1297 if(par->pll_ops && par->pll_ops->pll_to_var) 1348 if (par->pll_ops && par->pll_ops->pll_to_var)
1298 pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll)); 1349 pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll);
1299 else 1350 else
1300 pixclock_in_ps = 0; 1351 pixclock_in_ps = 0;
1301 1352
1302 if(0 == pixclock_in_ps) { 1353 if (0 == pixclock_in_ps) {
1303 PRINTKE("ALERT ops->pll_to_var get 0\n"); 1354 PRINTKE("ALERT ops->pll_to_var get 0\n");
1304 pixclock_in_ps = pixclock; 1355 pixclock_in_ps = pixclock;
1305 } 1356 }
1306 1357
1307 memset(&debug, 0, sizeof(debug)); 1358 memset(&debug, 0, sizeof(debug));
1308 if(!aty_crtc_to_var(&(par->crtc), &debug)) { 1359 if (!aty_crtc_to_var(&par->crtc, &debug)) {
1309 u32 hSync, vRefresh; 1360 u32 hSync, vRefresh;
1310 u32 h_disp, h_sync_strt, h_sync_end, h_total; 1361 u32 h_disp, h_sync_strt, h_sync_end, h_total;
1311 u32 v_disp, v_sync_strt, v_sync_end, v_total; 1362 u32 v_disp, v_sync_strt, v_sync_end, v_total;
@@ -1321,16 +1372,20 @@ static int atyfb_set_par(struct fb_info *info)
1321 1372
1322 hSync = 1000000000 / (pixclock_in_ps * h_total); 1373 hSync = 1000000000 / (pixclock_in_ps * h_total);
1323 vRefresh = (hSync * 1000) / v_total; 1374 vRefresh = (hSync * 1000) / v_total;
1324 if (par->crtc.gen_cntl & CRTC_INTERLACE_EN) 1375 if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
1325 vRefresh *= 2; 1376 vRefresh *= 2;
1326 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) 1377 if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1327 vRefresh /= 2; 1378 vRefresh /= 2;
1328 1379
1329 DPRINTK("atyfb_set_par\n"); 1380 DPRINTK("atyfb_set_par\n");
1330 DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel); 1381 DPRINTK(" Set Visible Mode to %ix%i-%i\n",
1331 DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n", 1382 var->xres, var->yres, var->bits_per_pixel);
1332 var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps); 1383 DPRINTK(" Virtual resolution %ix%i, "
1333 DPRINTK(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps); 1384 "pixclock_in_ps %i (calculated %i)\n",
1385 var->xres_virtual, var->yres_virtual,
1386 pixclock, pixclock_in_ps);
1387 DPRINTK(" Dot clock: %i MHz\n",
1388 1000000 / pixclock_in_ps);
1334 DPRINTK(" Horizontal sync: %i kHz\n", hSync); 1389 DPRINTK(" Horizontal sync: %i kHz\n", hSync);
1335 DPRINTK(" Vertical refresh: %i Hz\n", vRefresh); 1390 DPRINTK(" Vertical refresh: %i Hz\n", vRefresh);
1336 DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n", 1391 DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n",
@@ -1394,7 +1449,9 @@ static int atyfb_set_par(struct fb_info *info)
1394 } 1449 }
1395 aty_st_8(DAC_MASK, 0xff, par); 1450 aty_st_8(DAC_MASK, 0xff, par);
1396 1451
1397 info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8; 1452 info->fix.line_length = calc_line_length(par, var->xres_virtual,
1453 var->bits_per_pixel);
1454
1398 info->fix.visual = var->bits_per_pixel <= 8 ? 1455 info->fix.visual = var->bits_per_pixel <= 8 ?
1399 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; 1456 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1400 1457
@@ -1423,7 +1480,8 @@ static int atyfb_set_par(struct fb_info *info)
1423 base = 0x2000; 1480 base = 0x2000;
1424 printk("debug atyfb: Mach64 non-shadow register values:"); 1481 printk("debug atyfb: Mach64 non-shadow register values:");
1425 for (i = 0; i < 256; i = i+4) { 1482 for (i = 0; i < 256; i = i+4) {
1426 if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i); 1483 if (i % 16 == 0)
1484 printk("\ndebug atyfb: 0x%04X: ", base + i);
1427 printk(" %08X", aty_ld_le32(i, par)); 1485 printk(" %08X", aty_ld_le32(i, par));
1428 } 1486 }
1429 printk("\n\n"); 1487 printk("\n\n");
@@ -1433,8 +1491,10 @@ static int atyfb_set_par(struct fb_info *info)
1433 base = 0x00; 1491 base = 0x00;
1434 printk("debug atyfb: Mach64 PLL register values:"); 1492 printk("debug atyfb: Mach64 PLL register values:");
1435 for (i = 0; i < 64; i++) { 1493 for (i = 0; i < 64; i++) {
1436 if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i); 1494 if (i % 16 == 0)
1437 if(i%4 == 0) printk(" "); 1495 printk("\ndebug atyfb: 0x%02X: ", base + i);
1496 if (i % 4 == 0)
1497 printk(" ");
1438 printk("%02X", aty_ld_pll_ct(i, par)); 1498 printk("%02X", aty_ld_pll_ct(i, par));
1439 } 1499 }
1440 printk("\n\n"); 1500 printk("\n\n");
@@ -1445,19 +1505,21 @@ static int atyfb_set_par(struct fb_info *info)
1445 /* LCD registers */ 1505 /* LCD registers */
1446 base = 0x00; 1506 base = 0x00;
1447 printk("debug atyfb: LCD register values:"); 1507 printk("debug atyfb: LCD register values:");
1448 if(M64_HAS(LT_LCD_REGS)) { 1508 if (M64_HAS(LT_LCD_REGS)) {
1449 for(i = 0; i <= POWER_MANAGEMENT; i++) { 1509 for (i = 0; i <= POWER_MANAGEMENT; i++) {
1450 if(i == EXT_VERT_STRETCH) 1510 if (i == EXT_VERT_STRETCH)
1451 continue; 1511 continue;
1452 printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]); 1512 printk("\ndebug atyfb: 0x%04X: ",
1453 printk(" %08X", aty_ld_lcd(i, par)); 1513 lt_lcd_regs[i]);
1454 } 1514 printk(" %08X", aty_ld_lcd(i, par));
1455 1515 }
1456 } else { 1516 } else {
1457 for (i = 0; i < 64; i++) { 1517 for (i = 0; i < 64; i++) {
1458 if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i); 1518 if (i % 4 == 0)
1459 printk(" %08X", aty_ld_lcd(i, par)); 1519 printk("\ndebug atyfb: 0x%02X: ",
1460 } 1520 base + i);
1521 printk(" %08X", aty_ld_lcd(i, par));
1522 }
1461 } 1523 }
1462 printk("\n\n"); 1524 printk("\n\n");
1463 } 1525 }
@@ -1475,9 +1537,10 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1475 union aty_pll pll; 1537 union aty_pll pll;
1476 u32 pixclock; 1538 u32 pixclock;
1477 1539
1478 memcpy(&pll, &(par->pll), sizeof(pll)); 1540 memcpy(&pll, &par->pll, sizeof(pll));
1479 1541
1480 if((err = aty_var_to_crtc(info, var, &crtc))) 1542 err = aty_var_to_crtc(info, var, &crtc);
1543 if (err)
1481 return err; 1544 return err;
1482 1545
1483 pixclock = atyfb_get_pixclock(var, par); 1546 pixclock = atyfb_get_pixclock(var, par);
@@ -1487,7 +1550,9 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1487 PRINTKE("Invalid pixclock\n"); 1550 PRINTKE("Invalid pixclock\n");
1488 return -EINVAL; 1551 return -EINVAL;
1489 } else { 1552 } else {
1490 if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll))) 1553 err = par->pll_ops->var_to_pll(info, pixclock,
1554 var->bits_per_pixel, &pll);
1555 if (err)
1491 return err; 1556 return err;
1492 } 1557 }
1493 1558
@@ -1505,16 +1570,18 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
1505{ 1570{
1506 u32 xoffset = info->var.xoffset; 1571 u32 xoffset = info->var.xoffset;
1507 u32 yoffset = info->var.yoffset; 1572 u32 yoffset = info->var.yoffset;
1508 u32 vxres = par->crtc.vxres; 1573 u32 line_length = info->fix.line_length;
1509 u32 bpp = info->var.bits_per_pixel; 1574 u32 bpp = info->var.bits_per_pixel;
1510 1575
1511 par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19); 1576 par->crtc.off_pitch =
1577 ((yoffset * line_length + xoffset * bpp / 8) / 8) |
1578 ((line_length / bpp) << 22);
1512} 1579}
1513 1580
1514 1581
1515 /* 1582/*
1516 * Open/Release the frame buffer device 1583 * Open/Release the frame buffer device
1517 */ 1584 */
1518 1585
1519static int atyfb_open(struct fb_info *info, int user) 1586static int atyfb_open(struct fb_info *info, int user)
1520{ 1587{
@@ -1526,7 +1593,7 @@ static int atyfb_open(struct fb_info *info, int user)
1526 par->mmaped = 0; 1593 par->mmaped = 0;
1527#endif 1594#endif
1528 } 1595 }
1529 return (0); 1596 return 0;
1530} 1597}
1531 1598
1532static irqreturn_t aty_irq(int irq, void *dev_id) 1599static irqreturn_t aty_irq(int irq, void *dev_id)
@@ -1541,7 +1608,8 @@ static irqreturn_t aty_irq(int irq, void *dev_id)
1541 1608
1542 if (int_cntl & CRTC_VBLANK_INT) { 1609 if (int_cntl & CRTC_VBLANK_INT) {
1543 /* clear interrupt */ 1610 /* clear interrupt */
1544 aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par); 1611 aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) |
1612 CRTC_VBLANK_INT_AK, par);
1545 par->vblank.count++; 1613 par->vblank.count++;
1546 if (par->vblank.pan_display) { 1614 if (par->vblank.pan_display) {
1547 par->vblank.pan_display = 0; 1615 par->vblank.pan_display = 0;
@@ -1576,9 +1644,11 @@ static int aty_enable_irq(struct atyfb_par *par, int reenable)
1576 spin_lock_irq(&par->int_lock); 1644 spin_lock_irq(&par->int_lock);
1577 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK; 1645 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1578 if (!(int_cntl & CRTC_VBLANK_INT_EN)) { 1646 if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
1579 printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl); 1647 printk("atyfb: someone disabled IRQ [%08x]\n",
1648 int_cntl);
1580 /* re-enable interrupt */ 1649 /* re-enable interrupt */
1581 aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par ); 1650 aty_st_le32(CRTC_INT_CNTL, int_cntl |
1651 CRTC_VBLANK_INT_EN, par);
1582 } 1652 }
1583 spin_unlock_irq(&par->int_lock); 1653 spin_unlock_irq(&par->int_lock);
1584 } 1654 }
@@ -1598,7 +1668,7 @@ static int aty_disable_irq(struct atyfb_par *par)
1598 spin_lock_irq(&par->int_lock); 1668 spin_lock_irq(&par->int_lock);
1599 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK; 1669 int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1600 /* disable interrupt */ 1670 /* disable interrupt */
1601 aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par ); 1671 aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par);
1602 spin_unlock_irq(&par->int_lock); 1672 spin_unlock_irq(&par->int_lock);
1603 free_irq(par->irq, par); 1673 free_irq(par->irq, par);
1604 } 1674 }
@@ -1609,50 +1679,62 @@ static int aty_disable_irq(struct atyfb_par *par)
1609static int atyfb_release(struct fb_info *info, int user) 1679static int atyfb_release(struct fb_info *info, int user)
1610{ 1680{
1611 struct atyfb_par *par = (struct atyfb_par *) info->par; 1681 struct atyfb_par *par = (struct atyfb_par *) info->par;
1612 if (user) {
1613 par->open--;
1614 mdelay(1);
1615 wait_for_idle(par);
1616 if (!par->open) {
1617#ifdef __sparc__ 1682#ifdef __sparc__
1618 int was_mmaped = par->mmaped; 1683 int was_mmaped;
1684#endif
1619 1685
1620 par->mmaped = 0; 1686 if (!user)
1687 return 0;
1621 1688
1622 if (was_mmaped) { 1689 par->open--;
1623 struct fb_var_screeninfo var; 1690 mdelay(1);
1691 wait_for_idle(par);
1624 1692
1625 /* Now reset the default display config, we have no 1693 if (par->open)
1626 * idea what the program(s) which mmap'd the chip did 1694 return 0;
1627 * to the configuration, nor whether it restored it 1695
1628 * correctly. 1696#ifdef __sparc__
1629 */ 1697 was_mmaped = par->mmaped;
1630 var = default_var; 1698
1631 if (noaccel) 1699 par->mmaped = 0;
1632 var.accel_flags &= ~FB_ACCELF_TEXT; 1700
1633 else 1701 if (was_mmaped) {
1634 var.accel_flags |= FB_ACCELF_TEXT; 1702 struct fb_var_screeninfo var;
1635 if (var.yres == var.yres_virtual) { 1703
1636 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2)); 1704 /*
1637 var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual; 1705 * Now reset the default display config, we have
1638 if (var.yres_virtual < var.yres) 1706 * no idea what the program(s) which mmap'd the
1639 var.yres_virtual = var.yres; 1707 * chip did to the configuration, nor whether it
1640 } 1708 * restored it correctly.
1641 } 1709 */
1642#endif 1710 var = default_var;
1643 aty_disable_irq(par); 1711 if (noaccel)
1712 var.accel_flags &= ~FB_ACCELF_TEXT;
1713 else
1714 var.accel_flags |= FB_ACCELF_TEXT;
1715 if (var.yres == var.yres_virtual) {
1716 u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
1717 var.yres_virtual =
1718 ((videoram * 8) / var.bits_per_pixel) /
1719 var.xres_virtual;
1720 if (var.yres_virtual < var.yres)
1721 var.yres_virtual = var.yres;
1644 } 1722 }
1645 } 1723 }
1646 return (0); 1724#endif
1725 aty_disable_irq(par);
1726
1727 return 0;
1647} 1728}
1648 1729
1649 /* 1730/*
1650 * Pan or Wrap the Display 1731 * Pan or Wrap the Display
1651 * 1732 *
1652 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 1733 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1653 */ 1734 */
1654 1735
1655static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) 1736static int atyfb_pan_display(struct fb_var_screeninfo *var,
1737 struct fb_info *info)
1656{ 1738{
1657 struct atyfb_par *par = (struct atyfb_par *) info->par; 1739 struct atyfb_par *par = (struct atyfb_par *) info->par;
1658 u32 xres, yres, xoffset, yoffset; 1740 u32 xres, yres, xoffset, yoffset;
@@ -1663,7 +1745,8 @@ static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
1663 yres >>= 1; 1745 yres >>= 1;
1664 xoffset = (var->xoffset + 7) & ~7; 1746 xoffset = (var->xoffset + 7) & ~7;
1665 yoffset = var->yoffset; 1747 yoffset = var->yoffset;
1666 if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres) 1748 if (xoffset + xres > par->crtc.vxres ||
1749 yoffset + yres > par->crtc.vyres)
1667 return -EINVAL; 1750 return -EINVAL;
1668 info->var.xoffset = xoffset; 1751 info->var.xoffset = xoffset;
1669 info->var.yoffset = yoffset; 1752 info->var.yoffset = yoffset;
@@ -1700,10 +1783,10 @@ static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
1700 return ret; 1783 return ret;
1701 1784
1702 count = vbl->count; 1785 count = vbl->count;
1703 ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10); 1786 ret = wait_event_interruptible_timeout(vbl->wait,
1704 if (ret < 0) { 1787 count != vbl->count, HZ/10);
1788 if (ret < 0)
1705 return ret; 1789 return ret;
1706 }
1707 if (ret == 0) { 1790 if (ret == 0) {
1708 aty_enable_irq(par, 1); 1791 aty_enable_irq(par, 1);
1709 return -ETIMEDOUT; 1792 return -ETIMEDOUT;
@@ -1757,7 +1840,8 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1757 fbtyp.fb_depth = info->var.bits_per_pixel; 1840 fbtyp.fb_depth = info->var.bits_per_pixel;
1758 fbtyp.fb_cmsize = info->cmap.len; 1841 fbtyp.fb_cmsize = info->cmap.len;
1759 fbtyp.fb_size = info->fix.smem_len; 1842 fbtyp.fb_size = info->fix.smem_len;
1760 if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp))) 1843 if (copy_to_user((struct fbtype __user *) arg, &fbtyp,
1844 sizeof(fbtyp)))
1761 return -EFAULT; 1845 return -EFAULT;
1762 break; 1846 break;
1763#endif /* __sparc__ */ 1847#endif /* __sparc__ */
@@ -1777,7 +1861,7 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1777 case ATYIO_CLKR: 1861 case ATYIO_CLKR:
1778 if (M64_HAS(INTEGRATED)) { 1862 if (M64_HAS(INTEGRATED)) {
1779 struct atyclk clk; 1863 struct atyclk clk;
1780 union aty_pll *pll = &(par->pll); 1864 union aty_pll *pll = &par->pll;
1781 u32 dsp_config = pll->ct.dsp_config; 1865 u32 dsp_config = pll->ct.dsp_config;
1782 u32 dsp_on_off = pll->ct.dsp_on_off; 1866 u32 dsp_on_off = pll->ct.dsp_on_off;
1783 clk.ref_clk_per = par->ref_clk_per; 1867 clk.ref_clk_per = par->ref_clk_per;
@@ -1802,8 +1886,9 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1802 case ATYIO_CLKW: 1886 case ATYIO_CLKW:
1803 if (M64_HAS(INTEGRATED)) { 1887 if (M64_HAS(INTEGRATED)) {
1804 struct atyclk clk; 1888 struct atyclk clk;
1805 union aty_pll *pll = &(par->pll); 1889 union aty_pll *pll = &par->pll;
1806 if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk))) 1890 if (copy_from_user(&clk, (struct atyclk __user *) arg,
1891 sizeof(clk)))
1807 return -EFAULT; 1892 return -EFAULT;
1808 par->ref_clk_per = clk.ref_clk_per; 1893 par->ref_clk_per = clk.ref_clk_per;
1809 pll->ct.pll_ref_div = clk.pll_ref_div; 1894 pll->ct.pll_ref_div = clk.pll_ref_div;
@@ -1814,8 +1899,10 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1814 pll->ct.vclk_fb_div = clk.vclk_fb_div; 1899 pll->ct.vclk_fb_div = clk.vclk_fb_div;
1815 pll->ct.vclk_post_div_real = clk.vclk_post_div; 1900 pll->ct.vclk_post_div_real = clk.vclk_post_div;
1816 pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) | 1901 pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
1817 ((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20); 1902 ((clk.dsp_loop_latency & 0xf) << 16) |
1818 pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16); 1903 ((clk.dsp_precision & 7) << 20);
1904 pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) |
1905 ((clk.dsp_on & 0x7ff) << 16);
1819 /*aty_calc_pll_ct(info, &pll->ct);*/ 1906 /*aty_calc_pll_ct(info, &pll->ct);*/
1820 aty_set_pll_ct(info, pll); 1907 aty_set_pll_ct(info, pll);
1821 } else 1908 } else
@@ -1886,8 +1973,7 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1886 continue; 1973 continue;
1887 1974
1888 map_size = par->mmap_map[i].size - (offset - start); 1975 map_size = par->mmap_map[i].size - (offset - start);
1889 map_offset = 1976 map_offset = par->mmap_map[i].poff + (offset - start);
1890 par->mmap_map[i].poff + (offset - start);
1891 break; 1977 break;
1892 } 1978 }
1893 if (!map_size) { 1979 if (!map_size) {
@@ -1897,8 +1983,7 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1897 if (page + map_size > size) 1983 if (page + map_size > size)
1898 map_size = size - page; 1984 map_size = size - page;
1899 1985
1900 pgprot_val(vma->vm_page_prot) &= 1986 pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask);
1901 ~(par->mmap_map[i].prot_mask);
1902 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag; 1987 pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
1903 1988
1904 if (remap_pfn_range(vma, vma->vm_start + page, 1989 if (remap_pfn_range(vma, vma->vm_start + page,
@@ -2002,7 +2087,8 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2002 par->asleep = 1; 2087 par->asleep = 1;
2003 par->lock_blank = 1; 2088 par->lock_blank = 1;
2004 2089
2005 /* Because we may change PCI D state ourselves, we need to 2090 /*
2091 * Because we may change PCI D state ourselves, we need to
2006 * first save the config space content so the core can 2092 * first save the config space content so the core can
2007 * restore it properly on resume. 2093 * restore it properly on resume.
2008 */ 2094 */
@@ -2053,7 +2139,8 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
2053 2139
2054 acquire_console_sem(); 2140 acquire_console_sem();
2055 2141
2056 /* PCI state will have been restored by the core, so 2142 /*
2143 * PCI state will have been restored by the core, so
2057 * we should be in D0 now with our config space fully 2144 * we should be in D0 now with our config space fully
2058 * restored 2145 * restored
2059 */ 2146 */
@@ -2165,8 +2252,8 @@ static void aty_bl_init(struct atyfb_par *par)
2165 2252
2166 info->bl_dev = bd; 2253 info->bl_dev = bd;
2167 fb_bl_default_curve(info, 0, 2254 fb_bl_default_curve(info, 0,
2168 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, 2255 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2169 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); 2256 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2170 2257
2171 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; 2258 bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
2172 bd->props.brightness = bd->props.max_brightness; 2259 bd->props.brightness = bd->props.max_brightness;
@@ -2201,7 +2288,7 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2201 const int *refresh_tbl; 2288 const int *refresh_tbl;
2202 int i, size; 2289 int i, size;
2203 2290
2204 if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { 2291 if (M64_HAS(XL_MEM)) {
2205 refresh_tbl = ragexl_tbl; 2292 refresh_tbl = ragexl_tbl;
2206 size = ARRAY_SIZE(ragexl_tbl); 2293 size = ARRAY_SIZE(ragexl_tbl);
2207 } else { 2294 } else {
@@ -2209,16 +2296,16 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2209 size = ARRAY_SIZE(ragepro_tbl); 2296 size = ARRAY_SIZE(ragepro_tbl);
2210 } 2297 }
2211 2298
2212 for (i=0; i < size; i++) { 2299 for (i = 0; i < size; i++) {
2213 if (xclk < refresh_tbl[i]) 2300 if (xclk < refresh_tbl[i])
2214 break; 2301 break;
2215 } 2302 }
2216 par->mem_refresh_rate = i; 2303 par->mem_refresh_rate = i;
2217} 2304}
2218 2305
2219 /* 2306/*
2220 * Initialisation 2307 * Initialisation
2221 */ 2308 */
2222 2309
2223static struct fb_info *fb_list = NULL; 2310static struct fb_info *fb_list = NULL;
2224 2311
@@ -2335,7 +2422,10 @@ static int __devinit aty_init(struct fb_info *info)
2335 par->pll_ops = &aty_pll_ct; 2422 par->pll_ops = &aty_pll_ct;
2336 par->bus_type = PCI; 2423 par->bus_type = PCI;
2337 par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); 2424 par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
2338 ramname = aty_ct_ram[par->ram_type]; 2425 if (M64_HAS(XL_MEM))
2426 ramname = aty_xl_ram[par->ram_type];
2427 else
2428 ramname = aty_ct_ram[par->ram_type];
2339 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ 2429 /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
2340 if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) 2430 if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
2341 par->pll_limits.mclk = 63; 2431 par->pll_limits.mclk = 63;
@@ -2345,8 +2435,10 @@ static int __devinit aty_init(struct fb_info *info)
2345 } 2435 }
2346#endif 2436#endif
2347#ifdef CONFIG_PPC_PMAC 2437#ifdef CONFIG_PPC_PMAC
2348 /* The Apple iBook1 uses non-standard memory frequencies. We detect it 2438 /*
2349 * and set the frequency manually. */ 2439 * The Apple iBook1 uses non-standard memory frequencies.
2440 * We detect it and set the frequency manually.
2441 */
2350 if (machine_is_compatible("PowerBook2,1")) { 2442 if (machine_is_compatible("PowerBook2,1")) {
2351 par->pll_limits.mclk = 70; 2443 par->pll_limits.mclk = 70;
2352 par->pll_limits.xclk = 53; 2444 par->pll_limits.xclk = 53;
@@ -2390,14 +2482,15 @@ static int __devinit aty_init(struct fb_info *info)
2390#endif /* CONFIG_FB_ATY_CT */ 2482#endif /* CONFIG_FB_ATY_CT */
2391 2483
2392 /* save previous video mode */ 2484 /* save previous video mode */
2393 aty_get_crtc(par, &saved_crtc); 2485 aty_get_crtc(par, &par->saved_crtc);
2394 if(par->pll_ops->get_pll) 2486 if (par->pll_ops->get_pll)
2395 par->pll_ops->get_pll(info, &saved_pll); 2487 par->pll_ops->get_pll(info, &par->saved_pll);
2396 2488
2397 par->mem_cntl = aty_ld_le32(MEM_CNTL, par); 2489 par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
2398 gtb_memsize = M64_HAS(GTB_DSP); 2490 gtb_memsize = M64_HAS(GTB_DSP);
2399 if (gtb_memsize) 2491 if (gtb_memsize)
2400 switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ 2492 /* 0xF used instead of MEM_SIZE_ALIAS */
2493 switch (par->mem_cntl & 0xF) {
2401 case MEM_SIZE_512K: 2494 case MEM_SIZE_512K:
2402 info->fix.smem_len = 0x80000; 2495 info->fix.smem_len = 0x80000;
2403 break; 2496 break;
@@ -2466,8 +2559,8 @@ static int __devinit aty_init(struct fb_info *info)
2466 } 2559 }
2467 2560
2468 /* 2561 /*
2469 * Reg Block 0 (CT-compatible block) is at mmio_start 2562 * Reg Block 0 (CT-compatible block) is at mmio_start
2470 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400 2563 * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
2471 */ 2564 */
2472 if (M64_HAS(GX)) { 2565 if (M64_HAS(GX)) {
2473 info->fix.mmio_len = 0x400; 2566 info->fix.mmio_len = 0x400;
@@ -2486,84 +2579,98 @@ static int __devinit aty_init(struct fb_info *info)
2486 } 2579 }
2487 2580
2488 PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n", 2581 PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
2489 info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20), 2582 info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len>>20),
2490 info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max, 2583 info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal,
2491 par->pll_limits.mclk, par->pll_limits.xclk); 2584 par->pll_limits.pll_max, par->pll_limits.mclk,
2585 par->pll_limits.xclk);
2492 2586
2493#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) 2587#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
2494 if (M64_HAS(INTEGRATED)) { 2588 if (M64_HAS(INTEGRATED)) {
2495 int i; 2589 int i;
2496 printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL " 2590 printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL "
2497 "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n" 2591 "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG "
2498 "debug atyfb: %08x %08x %08x %08x %08x %08x %08x %08x\n" 2592 "DSP_ON_OFF CLOCK_CNTL\n"
2593 "debug atyfb: %08x %08x %08x "
2594 "%08x %08x %08x "
2595 "%08x %08x\n"
2499 "debug atyfb: PLL", 2596 "debug atyfb: PLL",
2500 aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par), 2597 aty_ld_le32(BUS_CNTL, par),
2501 aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par), 2598 aty_ld_le32(DAC_CNTL, par),
2502 aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par), 2599 aty_ld_le32(MEM_CNTL, par),
2503 aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par)); 2600 aty_ld_le32(EXT_MEM_CNTL, par),
2601 aty_ld_le32(CRTC_GEN_CNTL, par),
2602 aty_ld_le32(DSP_CONFIG, par),
2603 aty_ld_le32(DSP_ON_OFF, par),
2604 aty_ld_le32(CLOCK_CNTL, par));
2504 for (i = 0; i < 40; i++) 2605 for (i = 0; i < 40; i++)
2505 printk(" %02x", aty_ld_pll_ct(i, par)); 2606 printk(" %02x", aty_ld_pll_ct(i, par));
2506 printk("\n"); 2607 printk("\n");
2507 } 2608 }
2508#endif 2609#endif
2509 if(par->pll_ops->init_pll) 2610 if (par->pll_ops->init_pll)
2510 par->pll_ops->init_pll(info, &par->pll); 2611 par->pll_ops->init_pll(info, &par->pll);
2511 if (par->pll_ops->resume_pll) 2612 if (par->pll_ops->resume_pll)
2512 par->pll_ops->resume_pll(info, &par->pll); 2613 par->pll_ops->resume_pll(info, &par->pll);
2513 2614
2514 /* 2615 /*
2515 * Last page of 8 MB (4 MB on ISA) aperture is MMIO, 2616 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
2516 * unless the auxiliary register aperture is used. 2617 * unless the auxiliary register aperture is used.
2517 */ 2618 */
2518
2519 if (!par->aux_start && 2619 if (!par->aux_start &&
2520 (info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000))) 2620 (info->fix.smem_len == 0x800000 ||
2621 (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
2521 info->fix.smem_len -= GUI_RESERVE; 2622 info->fix.smem_len -= GUI_RESERVE;
2522 2623
2523 /* 2624 /*
2524 * Disable register access through the linear aperture 2625 * Disable register access through the linear aperture
2525 * if the auxiliary aperture is used so we can access 2626 * if the auxiliary aperture is used so we can access
2526 * the full 8 MB of video RAM on 8 MB boards. 2627 * the full 8 MB of video RAM on 8 MB boards.
2527 */ 2628 */
2528 if (par->aux_start) 2629 if (par->aux_start)
2529 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); 2630 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) |
2631 BUS_APER_REG_DIS, par);
2530 2632
2531#ifdef CONFIG_MTRR 2633#ifdef CONFIG_MTRR
2532 par->mtrr_aper = -1; 2634 par->mtrr_aper = -1;
2533 par->mtrr_reg = -1; 2635 par->mtrr_reg = -1;
2534 if (!nomtrr) { 2636 if (!nomtrr) {
2535 /* Cover the whole resource. */ 2637 /* Cover the whole resource. */
2536 par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1); 2638 par->mtrr_aper = mtrr_add(par->res_start, par->res_size,
2537 if (par->mtrr_aper >= 0 && !par->aux_start) { 2639 MTRR_TYPE_WRCOMB, 1);
2640 if (par->mtrr_aper >= 0 && !par->aux_start) {
2538 /* Make a hole for mmio. */ 2641 /* Make a hole for mmio. */
2539 par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE, 2642 par->mtrr_reg = mtrr_add(par->res_start + 0x800000 -
2540 GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1); 2643 GUI_RESERVE, GUI_RESERVE,
2644 MTRR_TYPE_UNCACHABLE, 1);
2541 if (par->mtrr_reg < 0) { 2645 if (par->mtrr_reg < 0) {
2542 mtrr_del(par->mtrr_aper, 0, 0); 2646 mtrr_del(par->mtrr_aper, 0, 0);
2543 par->mtrr_aper = -1; 2647 par->mtrr_aper = -1;
2544 } 2648 }
2545 } 2649 }
2546 } 2650 }
2547#endif 2651#endif
2548 2652
2549 info->fbops = &atyfb_ops; 2653 info->fbops = &atyfb_ops;
2550 info->pseudo_palette = par->pseudo_palette; 2654 info->pseudo_palette = par->pseudo_palette;
2551 info->flags = FBINFO_DEFAULT | 2655 info->flags = FBINFO_DEFAULT |
2552 FBINFO_HWACCEL_IMAGEBLIT | 2656 FBINFO_HWACCEL_IMAGEBLIT |
2553 FBINFO_HWACCEL_FILLRECT | 2657 FBINFO_HWACCEL_FILLRECT |
2554 FBINFO_HWACCEL_COPYAREA | 2658 FBINFO_HWACCEL_COPYAREA |
2555 FBINFO_HWACCEL_YPAN; 2659 FBINFO_HWACCEL_YPAN;
2556 2660
2557#ifdef CONFIG_PMAC_BACKLIGHT 2661#ifdef CONFIG_PMAC_BACKLIGHT
2558 if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { 2662 if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
2559 /* these bits let the 101 powerbook wake up from sleep -- paulus */ 2663 /*
2560 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) 2664 * these bits let the 101 powerbook
2561 | (USE_F32KHZ | TRISTATE_MEM_EN), par); 2665 * wake up from sleep -- paulus
2666 */
2667 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) |
2668 USE_F32KHZ | TRISTATE_MEM_EN, par);
2562 } else 2669 } else
2563#endif 2670#endif
2564 if (M64_HAS(MOBIL_BUS) && backlight) { 2671 if (M64_HAS(MOBIL_BUS) && backlight) {
2565#ifdef CONFIG_FB_ATY_BACKLIGHT 2672#ifdef CONFIG_FB_ATY_BACKLIGHT
2566 aty_bl_init (par); 2673 aty_bl_init(par);
2567#endif 2674#endif
2568 } 2675 }
2569 2676
@@ -2571,8 +2678,8 @@ static int __devinit aty_init(struct fb_info *info)
2571#ifdef CONFIG_PPC 2678#ifdef CONFIG_PPC
2572 if (machine_is(powermac)) { 2679 if (machine_is(powermac)) {
2573 /* 2680 /*
2574 * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it 2681 * FIXME: The NVRAM stuff should be put in a Mac-specific file,
2575 * applies to all Mac video cards 2682 * as it applies to all Mac video cards
2576 */ 2683 */
2577 if (mode) { 2684 if (mode) {
2578 if (mac_find_mode(&var, info, mode, 8)) 2685 if (mac_find_mode(&var, info, mode, 8))
@@ -2585,8 +2692,7 @@ static int __devinit aty_init(struct fb_info *info)
2585 default_vmode = VMODE_1024_768_60; 2692 default_vmode = VMODE_1024_768_60;
2586 else if (machine_is_compatible("iMac")) 2693 else if (machine_is_compatible("iMac"))
2587 default_vmode = VMODE_1024_768_75; 2694 default_vmode = VMODE_1024_768_75;
2588 else if (machine_is_compatible 2695 else if (machine_is_compatible("PowerBook2,1"))
2589 ("PowerBook2,1"))
2590 /* iBook with 800x600 LCD */ 2696 /* iBook with 800x600 LCD */
2591 default_vmode = VMODE_800_600_60; 2697 default_vmode = VMODE_800_600_60;
2592 else 2698 else
@@ -2600,7 +2706,7 @@ static int __devinit aty_init(struct fb_info *info)
2600 if (default_cmode < CMODE_8 || default_cmode > CMODE_32) 2706 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
2601 default_cmode = CMODE_8; 2707 default_cmode = CMODE_8;
2602 if (!mac_vmode_to_var(default_vmode, default_cmode, 2708 if (!mac_vmode_to_var(default_vmode, default_cmode,
2603 &var)) 2709 &var))
2604 has_var = 1; 2710 has_var = 1;
2605 } 2711 }
2606 } 2712 }
@@ -2667,17 +2773,17 @@ static int __devinit aty_init(struct fb_info *info)
2667 2773
2668aty_init_exit: 2774aty_init_exit:
2669 /* restore video mode */ 2775 /* restore video mode */
2670 aty_set_crtc(par, &saved_crtc); 2776 aty_set_crtc(par, &par->saved_crtc);
2671 par->pll_ops->set_pll(info, &saved_pll); 2777 par->pll_ops->set_pll(info, &par->saved_pll);
2672 2778
2673#ifdef CONFIG_MTRR 2779#ifdef CONFIG_MTRR
2674 if (par->mtrr_reg >= 0) { 2780 if (par->mtrr_reg >= 0) {
2675 mtrr_del(par->mtrr_reg, 0, 0); 2781 mtrr_del(par->mtrr_reg, 0, 0);
2676 par->mtrr_reg = -1; 2782 par->mtrr_reg = -1;
2677 } 2783 }
2678 if (par->mtrr_aper >= 0) { 2784 if (par->mtrr_aper >= 0) {
2679 mtrr_del(par->mtrr_aper, 0, 0); 2785 mtrr_del(par->mtrr_aper, 0, 0);
2680 par->mtrr_aper = -1; 2786 par->mtrr_aper = -1;
2681 } 2787 }
2682#endif 2788#endif
2683 return ret; 2789 return ret;
@@ -2705,18 +2811,18 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num)
2705 phys_size[m64_num] = size; 2811 phys_size[m64_num] = size;
2706 phys_guiregbase[m64_num] = guiregbase; 2812 phys_guiregbase[m64_num] = guiregbase;
2707 PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size, 2813 PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
2708 guiregbase); 2814 guiregbase);
2709 return 0; 2815 return 0;
2710 2816
2711 mach64_invalid: 2817 mach64_invalid:
2712 phys_vmembase[m64_num] = 0; 2818 phys_vmembase[m64_num] = 0;
2713 return -1; 2819 return -1;
2714} 2820}
2715#endif /* CONFIG_ATARI */ 2821#endif /* CONFIG_ATARI */
2716 2822
2717 /* 2823/*
2718 * Blank the display. 2824 * Blank the display.
2719 */ 2825 */
2720 2826
2721static int atyfb_blank(int blank, struct fb_info *info) 2827static int atyfb_blank(int blank, struct fb_info *info)
2722{ 2828{
@@ -2738,20 +2844,20 @@ static int atyfb_blank(int blank, struct fb_info *info)
2738 gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); 2844 gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
2739 gen_cntl &= ~0x400004c; 2845 gen_cntl &= ~0x400004c;
2740 switch (blank) { 2846 switch (blank) {
2741 case FB_BLANK_UNBLANK: 2847 case FB_BLANK_UNBLANK:
2742 break; 2848 break;
2743 case FB_BLANK_NORMAL: 2849 case FB_BLANK_NORMAL:
2744 gen_cntl |= 0x4000040; 2850 gen_cntl |= 0x4000040;
2745 break; 2851 break;
2746 case FB_BLANK_VSYNC_SUSPEND: 2852 case FB_BLANK_VSYNC_SUSPEND:
2747 gen_cntl |= 0x4000048; 2853 gen_cntl |= 0x4000048;
2748 break; 2854 break;
2749 case FB_BLANK_HSYNC_SUSPEND: 2855 case FB_BLANK_HSYNC_SUSPEND:
2750 gen_cntl |= 0x4000044; 2856 gen_cntl |= 0x4000044;
2751 break; 2857 break;
2752 case FB_BLANK_POWERDOWN: 2858 case FB_BLANK_POWERDOWN:
2753 gen_cntl |= 0x400004c; 2859 gen_cntl |= 0x400004c;
2754 break; 2860 break;
2755 } 2861 }
2756 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); 2862 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2757 2863
@@ -2776,15 +2882,15 @@ static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
2776 aty_st_8(DAC_DATA, blue, par); 2882 aty_st_8(DAC_DATA, blue, par);
2777} 2883}
2778 2884
2779 /* 2885/*
2780 * Set a single color register. The values supplied are already 2886 * Set a single color register. The values supplied are already
2781 * rounded down to the hardware's capabilities (according to the 2887 * rounded down to the hardware's capabilities (according to the
2782 * entries in the var structure). Return != 0 for invalid regno. 2888 * entries in the var structure). Return != 0 for invalid regno.
2783 * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR 2889 * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR
2784 */ 2890 */
2785 2891
2786static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 2892static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2787 u_int transp, struct fb_info *info) 2893 u_int transp, struct fb_info *info)
2788{ 2894{
2789 struct atyfb_par *par = (struct atyfb_par *) info->par; 2895 struct atyfb_par *par = (struct atyfb_par *) info->par;
2790 int i, depth; 2896 int i, depth;
@@ -2838,16 +2944,15 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2838 if (depth == 16) { 2944 if (depth == 16) {
2839 if (regno < 32) 2945 if (regno < 32)
2840 aty_st_pal(regno << 3, red, 2946 aty_st_pal(regno << 3, red,
2841 par->palette[regno<<1].green, 2947 par->palette[regno << 1].green,
2842 blue, par); 2948 blue, par);
2843 red = par->palette[regno>>1].red; 2949 red = par->palette[regno >> 1].red;
2844 blue = par->palette[regno>>1].blue; 2950 blue = par->palette[regno >> 1].blue;
2845 regno <<= 2; 2951 regno <<= 2;
2846 } else if (depth == 15) { 2952 } else if (depth == 15) {
2847 regno <<= 3; 2953 regno <<= 3;
2848 for(i = 0; i < 8; i++) { 2954 for (i = 0; i < 8; i++)
2849 aty_st_pal(regno + i, red, green, blue, par); 2955 aty_st_pal(regno + i, red, green, blue, par);
2850 }
2851 } 2956 }
2852 } 2957 }
2853 aty_st_pal(regno, red, green, blue, par); 2958 aty_st_pal(regno, red, green, blue, par);
@@ -2860,7 +2965,8 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2860#ifdef __sparc__ 2965#ifdef __sparc__
2861 2966
2862static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, 2967static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2863 struct fb_info *info, unsigned long addr) 2968 struct fb_info *info,
2969 unsigned long addr)
2864{ 2970{
2865 struct atyfb_par *par = info->par; 2971 struct atyfb_par *par = info->par;
2866 struct device_node *dp; 2972 struct device_node *dp;
@@ -2948,7 +3054,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2948 j++; 3054 j++;
2949 } 3055 }
2950 3056
2951 if((ret = correct_chipset(par))) 3057 ret = correct_chipset(par);
3058 if (ret)
2952 return ret; 3059 return ret;
2953 3060
2954 if (IS_XL(pdev->device)) { 3061 if (IS_XL(pdev->device)) {
@@ -3078,28 +3185,28 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3078 u32 driv_inf_tab, sig; 3185 u32 driv_inf_tab, sig;
3079 u16 lcd_ofs; 3186 u16 lcd_ofs;
3080 3187
3081 /* To support an LCD panel, we should know it's dimensions and 3188 /*
3189 * To support an LCD panel, we should know it's dimensions and
3082 * it's desired pixel clock. 3190 * it's desired pixel clock.
3083 * There are two ways to do it: 3191 * There are two ways to do it:
3084 * - Check the startup video mode and calculate the panel 3192 * - Check the startup video mode and calculate the panel
3085 * size from it. This is unreliable. 3193 * size from it. This is unreliable.
3086 * - Read it from the driver information table in the video BIOS. 3194 * - Read it from the driver information table in the video BIOS.
3087 */ 3195 */
3088 /* Address of driver information table is at offset 0x78. */ 3196 /* Address of driver information table is at offset 0x78. */
3089 driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78)); 3197 driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
3090 3198
3091 /* Check for the driver information table signature. */ 3199 /* Check for the driver information table signature. */
3092 sig = (*(u32 *)driv_inf_tab); 3200 sig = *(u32 *)driv_inf_tab;
3093 if ((sig == 0x54504c24) || /* Rage LT pro */ 3201 if ((sig == 0x54504c24) || /* Rage LT pro */
3094 (sig == 0x544d5224) || /* Rage mobility */ 3202 (sig == 0x544d5224) || /* Rage mobility */
3095 (sig == 0x54435824) || /* Rage XC */ 3203 (sig == 0x54435824) || /* Rage XC */
3096 (sig == 0x544c5824)) { /* Rage XL */ 3204 (sig == 0x544c5824)) { /* Rage XL */
3097 PRINTKI("BIOS contains driver information table.\n"); 3205 PRINTKI("BIOS contains driver information table.\n");
3098 lcd_ofs = (*(u16 *)(driv_inf_tab + 10)); 3206 lcd_ofs = *(u16 *)(driv_inf_tab + 10);
3099 par->lcd_table = 0; 3207 par->lcd_table = 0;
3100 if (lcd_ofs != 0) { 3208 if (lcd_ofs != 0)
3101 par->lcd_table = bios_base + lcd_ofs; 3209 par->lcd_table = bios_base + lcd_ofs;
3102 }
3103 } 3210 }
3104 3211
3105 if (par->lcd_table != 0) { 3212 if (par->lcd_table != 0) {
@@ -3114,14 +3221,16 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3114 u16 width, height, panel_type, refresh_rates; 3221 u16 width, height, panel_type, refresh_rates;
3115 u16 *lcdmodeptr; 3222 u16 *lcdmodeptr;
3116 u32 format; 3223 u32 format;
3117 u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200}; 3224 u8 lcd_refresh_rates[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85,
3118 /* The most important information is the panel size at 3225 90, 100, 120, 140, 150, 160, 200 };
3226 /*
3227 * The most important information is the panel size at
3119 * offset 25 and 27, but there's some other nice information 3228 * offset 25 and 27, but there's some other nice information
3120 * which we print to the screen. 3229 * which we print to the screen.
3121 */ 3230 */
3122 id = *(u8 *)par->lcd_table; 3231 id = *(u8 *)par->lcd_table;
3123 strncpy(model,(char *)par->lcd_table+1,24); 3232 strncpy(model, (char *)par->lcd_table+1, 24);
3124 model[23]=0; 3233 model[23] = 0;
3125 3234
3126 width = par->lcd_width = *(u16 *)(par->lcd_table+25); 3235 width = par->lcd_width = *(u16 *)(par->lcd_table+25);
3127 height = par->lcd_height = *(u16 *)(par->lcd_table+27); 3236 height = par->lcd_height = *(u16 *)(par->lcd_table+27);
@@ -3134,7 +3243,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3134 txtdual = "dual (split) "; 3243 txtdual = "dual (split) ";
3135 else 3244 else
3136 txtdual = ""; 3245 txtdual = "";
3137 tech = (panel_type>>2) & 63; 3246 tech = (panel_type >> 2) & 63;
3138 switch (tech) { 3247 switch (tech) {
3139 case 0: 3248 case 0:
3140 txtmonitor = "passive matrix"; 3249 txtmonitor = "passive matrix";
@@ -3194,22 +3303,24 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3194 } 3303 }
3195 } 3304 }
3196 PRINTKI("%s%s %s monitor detected: %s\n", 3305 PRINTKI("%s%s %s monitor detected: %s\n",
3197 txtdual ,txtcolour, txtmonitor, model); 3306 txtdual, txtcolour, txtmonitor, model);
3198 PRINTKI(" id=%d, %dx%d pixels, %s\n", 3307 PRINTKI(" id=%d, %dx%d pixels, %s\n",
3199 id, width, height, txtformat); 3308 id, width, height, txtformat);
3200 refresh_rates_buf[0] = 0; 3309 refresh_rates_buf[0] = 0;
3201 refresh_rates = *(u16 *)(par->lcd_table+62); 3310 refresh_rates = *(u16 *)(par->lcd_table+62);
3202 m = 1; 3311 m = 1;
3203 f = 0; 3312 f = 0;
3204 for (i=0;i<16;i++) { 3313 for (i = 0; i < 16; i++) {
3205 if (refresh_rates & m) { 3314 if (refresh_rates & m) {
3206 if (f == 0) { 3315 if (f == 0) {
3207 sprintf(strbuf, "%d", lcd_refresh_rates[i]); 3316 sprintf(strbuf, "%d",
3317 lcd_refresh_rates[i]);
3208 f++; 3318 f++;
3209 } else { 3319 } else {
3210 sprintf(strbuf, ",%d", lcd_refresh_rates[i]); 3320 sprintf(strbuf, ",%d",
3321 lcd_refresh_rates[i]);
3211 } 3322 }
3212 strcat(refresh_rates_buf,strbuf); 3323 strcat(refresh_rates_buf, strbuf);
3213 } 3324 }
3214 m = m << 1; 3325 m = m << 1;
3215 } 3326 }
@@ -3217,7 +3328,8 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3217 PRINTKI(" supports refresh rates [%s], default %d Hz\n", 3328 PRINTKI(" supports refresh rates [%s], default %d Hz\n",
3218 refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]); 3329 refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
3219 par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate]; 3330 par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
3220 /* We now need to determine the crtc parameters for the 3331 /*
3332 * We now need to determine the crtc parameters for the
3221 * LCD monitor. This is tricky, because they are not stored 3333 * LCD monitor. This is tricky, because they are not stored
3222 * individually in the BIOS. Instead, the BIOS contains a 3334 * individually in the BIOS. Instead, the BIOS contains a
3223 * table of display modes that work for this monitor. 3335 * table of display modes that work for this monitor.
@@ -3352,7 +3464,9 @@ static int __devinit init_from_bios(struct atyfb_par *par)
3352} 3464}
3353#endif /* __i386__ */ 3465#endif /* __i386__ */
3354 3466
3355static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr) 3467static int __devinit atyfb_setup_generic(struct pci_dev *pdev,
3468 struct fb_info *info,
3469 unsigned long addr)
3356{ 3470{
3357 struct atyfb_par *par = info->par; 3471 struct atyfb_par *par = info->par;
3358 u16 tmp; 3472 u16 tmp;
@@ -3399,10 +3513,12 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i
3399 goto atyfb_setup_generic_fail; 3513 goto atyfb_setup_generic_fail;
3400 } 3514 }
3401 3515
3402 if((ret = correct_chipset(par))) 3516 ret = correct_chipset(par);
3517 if (ret)
3403 goto atyfb_setup_generic_fail; 3518 goto atyfb_setup_generic_fail;
3404#ifdef __i386__ 3519#ifdef __i386__
3405 if((ret = init_from_bios(par))) 3520 ret = init_from_bios(par);
3521 if (ret)
3406 goto atyfb_setup_generic_fail; 3522 goto atyfb_setup_generic_fail;
3407#endif 3523#endif
3408 if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN)) 3524 if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
@@ -3427,7 +3543,8 @@ atyfb_setup_generic_fail:
3427 3543
3428#endif /* !__sparc__ */ 3544#endif /* !__sparc__ */
3429 3545
3430static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 3546static int __devinit atyfb_pci_probe(struct pci_dev *pdev,
3547 const struct pci_device_id *ent)
3431{ 3548{
3432 unsigned long addr, res_start, res_size; 3549 unsigned long addr, res_start, res_size;
3433 struct fb_info *info; 3550 struct fb_info *info;
@@ -3452,10 +3569,10 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3452 /* Reserve space */ 3569 /* Reserve space */
3453 res_start = rp->start; 3570 res_start = rp->start;
3454 res_size = rp->end - rp->start + 1; 3571 res_size = rp->end - rp->start + 1;
3455 if (!request_mem_region (res_start, res_size, "atyfb")) 3572 if (!request_mem_region(res_start, res_size, "atyfb"))
3456 return -EBUSY; 3573 return -EBUSY;
3457 3574
3458 /* Allocate framebuffer */ 3575 /* Allocate framebuffer */
3459 info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev); 3576 info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
3460 if (!info) { 3577 if (!info) {
3461 PRINTKE("atyfb_pci_probe() can't alloc fb_info\n"); 3578 PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
@@ -3502,6 +3619,11 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3502 par->mmap_map[1].prot_flag = _PAGE_E; 3619 par->mmap_map[1].prot_flag = _PAGE_E;
3503#endif /* __sparc__ */ 3620#endif /* __sparc__ */
3504 3621
3622 mutex_lock(&reboot_lock);
3623 if (!reboot_info)
3624 reboot_info = info;
3625 mutex_unlock(&reboot_lock);
3626
3505 return 0; 3627 return 0;
3506 3628
3507err_release_io: 3629err_release_io:
@@ -3538,7 +3660,8 @@ static int __init atyfb_atari_probe(void)
3538 for (m64_num = 0; m64_num < mach64_count; m64_num++) { 3660 for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3539 if (!phys_vmembase[m64_num] || !phys_size[m64_num] || 3661 if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3540 !phys_guiregbase[m64_num]) { 3662 !phys_guiregbase[m64_num]) {
3541 PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num); 3663 PRINTKI("phys_*[%d] parameters not set => "
3664 "returning early. \n", m64_num);
3542 continue; 3665 continue;
3543 } 3666 }
3544 3667
@@ -3554,8 +3677,8 @@ static int __init atyfb_atari_probe(void)
3554 par->irq = (unsigned int) -1; /* something invalid */ 3677 par->irq = (unsigned int) -1; /* something invalid */
3555 3678
3556 /* 3679 /*
3557 * Map the video memory (physical address given) to somewhere in the 3680 * Map the video memory (physical address given)
3558 * kernel address space. 3681 * to somewhere in the kernel address space.
3559 */ 3682 */
3560 info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]); 3683 info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
3561 info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */ 3684 info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
@@ -3614,8 +3737,8 @@ static void __devexit atyfb_remove(struct fb_info *info)
3614 struct atyfb_par *par = (struct atyfb_par *) info->par; 3737 struct atyfb_par *par = (struct atyfb_par *) info->par;
3615 3738
3616 /* restore video mode */ 3739 /* restore video mode */
3617 aty_set_crtc(par, &saved_crtc); 3740 aty_set_crtc(par, &par->saved_crtc);
3618 par->pll_ops->set_pll(info, &saved_pll); 3741 par->pll_ops->set_pll(info, &par->saved_pll);
3619 3742
3620 unregister_framebuffer(info); 3743 unregister_framebuffer(info);
3621 3744
@@ -3626,12 +3749,12 @@ static void __devexit atyfb_remove(struct fb_info *info)
3626 3749
3627#ifdef CONFIG_MTRR 3750#ifdef CONFIG_MTRR
3628 if (par->mtrr_reg >= 0) { 3751 if (par->mtrr_reg >= 0) {
3629 mtrr_del(par->mtrr_reg, 0, 0); 3752 mtrr_del(par->mtrr_reg, 0, 0);
3630 par->mtrr_reg = -1; 3753 par->mtrr_reg = -1;
3631 } 3754 }
3632 if (par->mtrr_aper >= 0) { 3755 if (par->mtrr_aper >= 0) {
3633 mtrr_del(par->mtrr_aper, 0, 0); 3756 mtrr_del(par->mtrr_aper, 0, 0);
3634 par->mtrr_aper = -1; 3757 par->mtrr_aper = -1;
3635 } 3758 }
3636#endif 3759#endif
3637#ifndef __sparc__ 3760#ifndef __sparc__
@@ -3661,6 +3784,11 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
3661{ 3784{
3662 struct fb_info *info = pci_get_drvdata(pdev); 3785 struct fb_info *info = pci_get_drvdata(pdev);
3663 3786
3787 mutex_lock(&reboot_lock);
3788 if (reboot_info == info)
3789 reboot_info = NULL;
3790 mutex_unlock(&reboot_lock);
3791
3664 atyfb_remove(info); 3792 atyfb_remove(info);
3665} 3793}
3666 3794
@@ -3808,29 +3936,88 @@ static int __init atyfb_setup(char *options)
3808} 3936}
3809#endif /* MODULE */ 3937#endif /* MODULE */
3810 3938
3939static int atyfb_reboot_notify(struct notifier_block *nb,
3940 unsigned long code, void *unused)
3941{
3942 struct atyfb_par *par;
3943
3944 if (code != SYS_RESTART)
3945 return NOTIFY_DONE;
3946
3947 mutex_lock(&reboot_lock);
3948
3949 if (!reboot_info)
3950 goto out;
3951
3952 if (!lock_fb_info(reboot_info))
3953 goto out;
3954
3955 par = reboot_info->par;
3956
3957 /*
3958 * HP OmniBook 500's BIOS doesn't like the state of the
3959 * hardware after atyfb has been used. Restore the hardware
3960 * to the original state to allow successful reboots.
3961 */
3962 aty_set_crtc(par, &par->saved_crtc);
3963 par->pll_ops->set_pll(reboot_info, &par->saved_pll);
3964
3965 unlock_fb_info(reboot_info);
3966 out:
3967 mutex_unlock(&reboot_lock);
3968
3969 return NOTIFY_DONE;
3970}
3971
3972static struct notifier_block atyfb_reboot_notifier = {
3973 .notifier_call = atyfb_reboot_notify,
3974};
3975
3976static const struct dmi_system_id atyfb_reboot_ids[] = {
3977 {
3978 .ident = "HP OmniBook 500",
3979 .matches = {
3980 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
3981 DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
3982 DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
3983 },
3984 },
3985
3986 { }
3987};
3988
3811static int __init atyfb_init(void) 3989static int __init atyfb_init(void)
3812{ 3990{
3813 int err1 = 1, err2 = 1; 3991 int err1 = 1, err2 = 1;
3814#ifndef MODULE 3992#ifndef MODULE
3815 char *option = NULL; 3993 char *option = NULL;
3816 3994
3817 if (fb_get_options("atyfb", &option)) 3995 if (fb_get_options("atyfb", &option))
3818 return -ENODEV; 3996 return -ENODEV;
3819 atyfb_setup(option); 3997 atyfb_setup(option);
3820#endif 3998#endif
3821 3999
3822#ifdef CONFIG_PCI 4000#ifdef CONFIG_PCI
3823 err1 = pci_register_driver(&atyfb_driver); 4001 err1 = pci_register_driver(&atyfb_driver);
3824#endif 4002#endif
3825#ifdef CONFIG_ATARI 4003#ifdef CONFIG_ATARI
3826 err2 = atyfb_atari_probe(); 4004 err2 = atyfb_atari_probe();
3827#endif 4005#endif
3828 4006
3829 return (err1 && err2) ? -ENODEV : 0; 4007 if (err1 && err2)
4008 return -ENODEV;
4009
4010 if (dmi_check_system(atyfb_reboot_ids))
4011 register_reboot_notifier(&atyfb_reboot_notifier);
4012
4013 return 0;
3830} 4014}
3831 4015
3832static void __exit atyfb_exit(void) 4016static void __exit atyfb_exit(void)
3833{ 4017{
4018 if (dmi_check_system(atyfb_reboot_ids))
4019 unregister_reboot_notifier(&atyfb_reboot_notifier);
4020
3834#ifdef CONFIG_PCI 4021#ifdef CONFIG_PCI
3835 pci_unregister_driver(&atyfb_driver); 4022 pci_unregister_driver(&atyfb_driver);
3836#endif 4023#endif
@@ -3852,8 +4039,7 @@ MODULE_PARM_DESC(mclk, "int: override memory clock");
3852module_param(xclk, int, 0); 4039module_param(xclk, int, 0);
3853MODULE_PARM_DESC(xclk, "int: override accelerated engine clock"); 4040MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
3854module_param(comp_sync, int, 0); 4041module_param(comp_sync, int, 0);
3855MODULE_PARM_DESC(comp_sync, 4042MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)");
3856 "Set composite sync signal to low (0) or high (1)");
3857module_param(mode, charp, 0); 4043module_param(mode, charp, 0);
3858MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); 4044MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
3859#ifdef CONFIG_MTRR 4045#ifdef CONFIG_MTRR
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index 0cc9724e61a2..51fcc0a2c94a 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -63,14 +63,17 @@ static void reset_GTC_3D_engine(const struct atyfb_par *par)
63void aty_init_engine(struct atyfb_par *par, struct fb_info *info) 63void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
64{ 64{
65 u32 pitch_value; 65 u32 pitch_value;
66 u32 vxres;
66 67
67 /* determine modal information from global mode structure */ 68 /* determine modal information from global mode structure */
68 pitch_value = info->var.xres_virtual; 69 pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8);
70 vxres = info->var.xres_virtual;
69 71
70 if (info->var.bits_per_pixel == 24) { 72 if (info->var.bits_per_pixel == 24) {
71 /* In 24 bpp, the engine is in 8 bpp - this requires that all */ 73 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
72 /* horizontal coordinates and widths must be adjusted */ 74 /* horizontal coordinates and widths must be adjusted */
73 pitch_value *= 3; 75 pitch_value *= 3;
76 vxres *= 3;
74 } 77 }
75 78
76 /* On GTC (RagePro), we need to reset the 3D engine before */ 79 /* On GTC (RagePro), we need to reset the 3D engine before */
@@ -133,7 +136,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
133 aty_st_le32(SC_LEFT, 0, par); 136 aty_st_le32(SC_LEFT, 0, par);
134 aty_st_le32(SC_TOP, 0, par); 137 aty_st_le32(SC_TOP, 0, par);
135 aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par); 138 aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par);
136 aty_st_le32(SC_RIGHT, pitch_value - 1, par); 139 aty_st_le32(SC_RIGHT, vxres - 1, par);
137 140
138 /* set background color to minimum value (usually BLACK) */ 141 /* set background color to minimum value (usually BLACK) */
139 aty_st_le32(DP_BKGD_CLR, 0, par); 142 aty_st_le32(DP_BKGD_CLR, 0, par);
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 378f27745a1d..a699aab63820 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -715,8 +715,11 @@ int au1100fb_setup(char *options)
715 } 715 }
716 /* Mode option (only option that start with digit) */ 716 /* Mode option (only option that start with digit) */
717 else if (isdigit(this_opt[0])) { 717 else if (isdigit(this_opt[0])) {
718 mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); 718 mode = kstrdup(this_opt, GFP_KERNEL);
719 strncpy(mode, this_opt, strlen(this_opt) + 1); 719 if (!mode) {
720 print_err("memory allocation failed");
721 return -ENOMEM;
722 }
720 } 723 }
721 /* Unsupported option */ 724 /* Unsupported option */
722 else { 725 else {
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index f9d19be05540..09bfa9662e4d 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -31,6 +31,13 @@ config LCD_CORGI
31 Say y here to support the LCD panels usually found on SHARP 31 Say y here to support the LCD panels usually found on SHARP
32 corgi (C7x0) and spitz (Cxx00) models. 32 corgi (C7x0) and spitz (Cxx00) models.
33 33
34config LCD_LMS283GF05
35 tristate "Samsung LMS283GF05 LCD"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO
37 help
38 SPI driver for Samsung LMS283GF05. This provides basic support
39 for powering the LCD up/down through a sysfs interface.
40
34config LCD_LTV350QV 41config LCD_LTV350QV
35 tristate "Samsung LTV350QV LCD Panel" 42 tristate "Samsung LTV350QV LCD Panel"
36 depends on LCD_CLASS_DEVICE && SPI_MASTER 43 depends on LCD_CLASS_DEVICE && SPI_MASTER
@@ -110,7 +117,7 @@ config BACKLIGHT_CLASS_DEVICE
110config BACKLIGHT_ATMEL_LCDC 117config BACKLIGHT_ATMEL_LCDC
111 bool "Atmel LCDC Contrast-as-Backlight control" 118 bool "Atmel LCDC Contrast-as-Backlight control"
112 depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL 119 depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL
113 default y if MACH_SAM9261EK || MACH_SAM9263EK 120 default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK
114 help 121 help
115 This provides a backlight control internal to the Atmel LCDC 122 This provides a backlight control internal to the Atmel LCDC
116 driver. If the LCD "contrast control" on your board is wired 123 driver. If the LCD "contrast control" on your board is wired
@@ -229,3 +236,29 @@ config BACKLIGHT_SAHARA
229 help 236 help
230 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the 237 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
231 backlight driver. 238 backlight driver.
239
240config BACKLIGHT_WM831X
241 tristate "WM831x PMIC Backlight Driver"
242 depends on BACKLIGHT_CLASS_DEVICE && MFD_WM831X
243 help
244 If you have a backlight driven by the ISINK and DCDC of a
245 WM831x PMIC say y to enable the backlight driver for it.
246
247config BACKLIGHT_ADX
248 tristate "Avionic Design Xanthos Backlight Driver"
249 depends on BACKLIGHT_CLASS_DEVICE && ARCH_PXA_ADX
250 default y
251 help
252 Say Y to enable the backlight driver on Avionic Design Xanthos-based
253 boards.
254
255config BACKLIGHT_ADP5520
256 tristate "Backlight Driver for ADP5520/ADP5501 using WLED"
257 depends on BACKLIGHT_CLASS_DEVICE && PMIC_ADP5520
258 help
259 If you have a LCD backlight connected to the BST/BL_SNK output of
260 ADP5520 or ADP5501, say Y here to enable this driver.
261
262 To compile this driver as a module, choose M here: the module will
263 be called adp5520_bl.
264
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 4eb178c1d684..9a405548874c 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,6 +3,7 @@
3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o 3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o 4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
5obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o 5obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
6obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
6obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o 7obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
7obj-$(CONFIG_LCD_ILI9320) += ili9320.o 8obj-$(CONFIG_LCD_ILI9320) += ili9320.o
8obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o 9obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
@@ -24,4 +25,7 @@ obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
24obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o 25obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
25obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o 26obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
26obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o 27obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
28obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
29obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
30obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
27 31
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
new file mode 100644
index 000000000000..ad05da5ba3c7
--- /dev/null
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -0,0 +1,377 @@
1/*
2 * Backlight driver for Analog Devices ADP5520/ADP5501 MFD PMICs
3 *
4 * Copyright 2009 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/platform_device.h>
12#include <linux/fb.h>
13#include <linux/backlight.h>
14#include <linux/mfd/adp5520.h>
15
16struct adp5520_bl {
17 struct device *master;
18 struct adp5520_backlight_platfrom_data *pdata;
19 struct mutex lock;
20 unsigned long cached_daylight_max;
21 int id;
22 int current_brightness;
23};
24
25static int adp5520_bl_set(struct backlight_device *bl, int brightness)
26{
27 struct adp5520_bl *data = bl_get_data(bl);
28 struct device *master = data->master;
29 int ret = 0;
30
31 if (data->pdata->en_ambl_sens) {
32 if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) {
33 /* Disable Ambient Light auto adjust */
34 ret |= adp5520_clr_bits(master, BL_CONTROL,
35 BL_AUTO_ADJ);
36 ret |= adp5520_write(master, DAYLIGHT_MAX, brightness);
37 } else {
38 /*
39 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
40 * restore daylight l3 sysfs brightness
41 */
42 ret |= adp5520_write(master, DAYLIGHT_MAX,
43 data->cached_daylight_max);
44 ret |= adp5520_set_bits(master, BL_CONTROL,
45 BL_AUTO_ADJ);
46 }
47 } else {
48 ret |= adp5520_write(master, DAYLIGHT_MAX, brightness);
49 }
50
51 if (data->current_brightness && brightness == 0)
52 ret |= adp5520_set_bits(master,
53 MODE_STATUS, DIM_EN);
54 else if (data->current_brightness == 0 && brightness)
55 ret |= adp5520_clr_bits(master,
56 MODE_STATUS, DIM_EN);
57
58 if (!ret)
59 data->current_brightness = brightness;
60
61 return ret;
62}
63
64static int adp5520_bl_update_status(struct backlight_device *bl)
65{
66 int brightness = bl->props.brightness;
67 if (bl->props.power != FB_BLANK_UNBLANK)
68 brightness = 0;
69
70 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
71 brightness = 0;
72
73 return adp5520_bl_set(bl, brightness);
74}
75
76static int adp5520_bl_get_brightness(struct backlight_device *bl)
77{
78 struct adp5520_bl *data = bl_get_data(bl);
79 int error;
80 uint8_t reg_val;
81
82 error = adp5520_read(data->master, BL_VALUE, &reg_val);
83
84 return error ? data->current_brightness : reg_val;
85}
86
87static struct backlight_ops adp5520_bl_ops = {
88 .update_status = adp5520_bl_update_status,
89 .get_brightness = adp5520_bl_get_brightness,
90};
91
92static int adp5520_bl_setup(struct backlight_device *bl)
93{
94 struct adp5520_bl *data = bl_get_data(bl);
95 struct device *master = data->master;
96 struct adp5520_backlight_platfrom_data *pdata = data->pdata;
97 int ret = 0;
98
99 ret |= adp5520_write(master, DAYLIGHT_MAX, pdata->l1_daylight_max);
100 ret |= adp5520_write(master, DAYLIGHT_DIM, pdata->l1_daylight_dim);
101
102 if (pdata->en_ambl_sens) {
103 data->cached_daylight_max = pdata->l1_daylight_max;
104 ret |= adp5520_write(master, OFFICE_MAX, pdata->l2_office_max);
105 ret |= adp5520_write(master, OFFICE_DIM, pdata->l2_office_dim);
106 ret |= adp5520_write(master, DARK_MAX, pdata->l3_dark_max);
107 ret |= adp5520_write(master, DARK_DIM, pdata->l3_dark_dim);
108 ret |= adp5520_write(master, L2_TRIP, pdata->l2_trip);
109 ret |= adp5520_write(master, L2_HYS, pdata->l2_hyst);
110 ret |= adp5520_write(master, L3_TRIP, pdata->l3_trip);
111 ret |= adp5520_write(master, L3_HYS, pdata->l3_hyst);
112 ret |= adp5520_write(master, ALS_CMPR_CFG,
113 ALS_CMPR_CFG_VAL(pdata->abml_filt, L3_EN));
114 }
115
116 ret |= adp5520_write(master, BL_CONTROL,
117 BL_CTRL_VAL(pdata->fade_led_law, pdata->en_ambl_sens));
118
119 ret |= adp5520_write(master, BL_FADE, FADE_VAL(pdata->fade_in,
120 pdata->fade_out));
121
122 ret |= adp5520_set_bits(master, MODE_STATUS, BL_EN | DIM_EN);
123
124 return ret;
125}
126
127static ssize_t adp5520_show(struct device *dev, char *buf, int reg)
128{
129 struct adp5520_bl *data = dev_get_drvdata(dev);
130 int error;
131 uint8_t reg_val;
132
133 mutex_lock(&data->lock);
134 error = adp5520_read(data->master, reg, &reg_val);
135 mutex_unlock(&data->lock);
136
137 return sprintf(buf, "%u\n", reg_val);
138}
139
140static ssize_t adp5520_store(struct device *dev, const char *buf,
141 size_t count, int reg)
142{
143 struct adp5520_bl *data = dev_get_drvdata(dev);
144 unsigned long val;
145 int ret;
146
147 ret = strict_strtoul(buf, 10, &val);
148 if (ret)
149 return ret;
150
151 mutex_lock(&data->lock);
152 adp5520_write(data->master, reg, val);
153 mutex_unlock(&data->lock);
154
155 return count;
156}
157
158static ssize_t adp5520_bl_dark_max_show(struct device *dev,
159 struct device_attribute *attr, char *buf)
160{
161 return adp5520_show(dev, buf, DARK_MAX);
162}
163
164static ssize_t adp5520_bl_dark_max_store(struct device *dev,
165 struct device_attribute *attr, const char *buf, size_t count)
166{
167 return adp5520_store(dev, buf, count, DARK_MAX);
168}
169static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show,
170 adp5520_bl_dark_max_store);
171
172static ssize_t adp5520_bl_office_max_show(struct device *dev,
173 struct device_attribute *attr, char *buf)
174{
175 return adp5520_show(dev, buf, OFFICE_MAX);
176}
177
178static ssize_t adp5520_bl_office_max_store(struct device *dev,
179 struct device_attribute *attr, const char *buf, size_t count)
180{
181 return adp5520_store(dev, buf, count, OFFICE_MAX);
182}
183static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show,
184 adp5520_bl_office_max_store);
185
186static ssize_t adp5520_bl_daylight_max_show(struct device *dev,
187 struct device_attribute *attr, char *buf)
188{
189 return adp5520_show(dev, buf, DAYLIGHT_MAX);
190}
191
192static ssize_t adp5520_bl_daylight_max_store(struct device *dev,
193 struct device_attribute *attr, const char *buf, size_t count)
194{
195 struct adp5520_bl *data = dev_get_drvdata(dev);
196
197 strict_strtoul(buf, 10, &data->cached_daylight_max);
198 return adp5520_store(dev, buf, count, DAYLIGHT_MAX);
199}
200static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show,
201 adp5520_bl_daylight_max_store);
202
203static ssize_t adp5520_bl_dark_dim_show(struct device *dev,
204 struct device_attribute *attr, char *buf)
205{
206 return adp5520_show(dev, buf, DARK_DIM);
207}
208
209static ssize_t adp5520_bl_dark_dim_store(struct device *dev,
210 struct device_attribute *attr,
211 const char *buf, size_t count)
212{
213 return adp5520_store(dev, buf, count, DARK_DIM);
214}
215static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show,
216 adp5520_bl_dark_dim_store);
217
218static ssize_t adp5520_bl_office_dim_show(struct device *dev,
219 struct device_attribute *attr, char *buf)
220{
221 return adp5520_show(dev, buf, OFFICE_DIM);
222}
223
224static ssize_t adp5520_bl_office_dim_store(struct device *dev,
225 struct device_attribute *attr,
226 const char *buf, size_t count)
227{
228 return adp5520_store(dev, buf, count, OFFICE_DIM);
229}
230static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show,
231 adp5520_bl_office_dim_store);
232
233static ssize_t adp5520_bl_daylight_dim_show(struct device *dev,
234 struct device_attribute *attr, char *buf)
235{
236 return adp5520_show(dev, buf, DAYLIGHT_DIM);
237}
238
239static ssize_t adp5520_bl_daylight_dim_store(struct device *dev,
240 struct device_attribute *attr,
241 const char *buf, size_t count)
242{
243 return adp5520_store(dev, buf, count, DAYLIGHT_DIM);
244}
245static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show,
246 adp5520_bl_daylight_dim_store);
247
248static struct attribute *adp5520_bl_attributes[] = {
249 &dev_attr_dark_max.attr,
250 &dev_attr_dark_dim.attr,
251 &dev_attr_office_max.attr,
252 &dev_attr_office_dim.attr,
253 &dev_attr_daylight_max.attr,
254 &dev_attr_daylight_dim.attr,
255 NULL
256};
257
258static const struct attribute_group adp5520_bl_attr_group = {
259 .attrs = adp5520_bl_attributes,
260};
261
262static int __devinit adp5520_bl_probe(struct platform_device *pdev)
263{
264 struct backlight_device *bl;
265 struct adp5520_bl *data;
266 int ret = 0;
267
268 data = kzalloc(sizeof(*data), GFP_KERNEL);
269 if (data == NULL)
270 return -ENOMEM;
271
272 data->master = pdev->dev.parent;
273 data->pdata = pdev->dev.platform_data;
274
275 if (data->pdata == NULL) {
276 dev_err(&pdev->dev, "missing platform data\n");
277 kfree(data);
278 return -ENODEV;
279 }
280
281 data->id = pdev->id;
282 data->current_brightness = 0;
283
284 mutex_init(&data->lock);
285
286 bl = backlight_device_register(pdev->name, data->master,
287 data, &adp5520_bl_ops);
288 if (IS_ERR(bl)) {
289 dev_err(&pdev->dev, "failed to register backlight\n");
290 kfree(data);
291 return PTR_ERR(bl);
292 }
293
294 bl->props.max_brightness =
295 bl->props.brightness = ADP5020_MAX_BRIGHTNESS;
296
297 if (data->pdata->en_ambl_sens)
298 ret = sysfs_create_group(&bl->dev.kobj,
299 &adp5520_bl_attr_group);
300
301 if (ret) {
302 dev_err(&pdev->dev, "failed to register sysfs\n");
303 backlight_device_unregister(bl);
304 kfree(data);
305 }
306
307 platform_set_drvdata(pdev, bl);
308 ret |= adp5520_bl_setup(bl);
309 backlight_update_status(bl);
310
311 return ret;
312}
313
314static int __devexit adp5520_bl_remove(struct platform_device *pdev)
315{
316 struct backlight_device *bl = platform_get_drvdata(pdev);
317 struct adp5520_bl *data = bl_get_data(bl);
318
319 adp5520_clr_bits(data->master, MODE_STATUS, BL_EN);
320
321 if (data->pdata->en_ambl_sens)
322 sysfs_remove_group(&bl->dev.kobj,
323 &adp5520_bl_attr_group);
324
325 backlight_device_unregister(bl);
326 kfree(data);
327
328 return 0;
329}
330
331#ifdef CONFIG_PM
332static int adp5520_bl_suspend(struct platform_device *pdev,
333 pm_message_t state)
334{
335 struct backlight_device *bl = platform_get_drvdata(pdev);
336 return adp5520_bl_set(bl, 0);
337}
338
339static int adp5520_bl_resume(struct platform_device *pdev)
340{
341 struct backlight_device *bl = platform_get_drvdata(pdev);
342
343 backlight_update_status(bl);
344 return 0;
345}
346#else
347#define adp5520_bl_suspend NULL
348#define adp5520_bl_resume NULL
349#endif
350
351static struct platform_driver adp5520_bl_driver = {
352 .driver = {
353 .name = "adp5520-backlight",
354 .owner = THIS_MODULE,
355 },
356 .probe = adp5520_bl_probe,
357 .remove = __devexit_p(adp5520_bl_remove),
358 .suspend = adp5520_bl_suspend,
359 .resume = adp5520_bl_resume,
360};
361
362static int __init adp5520_bl_init(void)
363{
364 return platform_driver_register(&adp5520_bl_driver);
365}
366module_init(adp5520_bl_init);
367
368static void __exit adp5520_bl_exit(void)
369{
370 platform_driver_unregister(&adp5520_bl_driver);
371}
372module_exit(adp5520_bl_exit);
373
374MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
375MODULE_DESCRIPTION("ADP5520(01) Backlight Driver");
376MODULE_LICENSE("GPL");
377MODULE_ALIAS("platform:adp5520-backlight");
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
new file mode 100644
index 000000000000..2c3bdfc620b7
--- /dev/null
+++ b/drivers/video/backlight/adx_bl.c
@@ -0,0 +1,178 @@
1/*
2 * linux/drivers/video/backlight/adx.c
3 *
4 * Copyright (C) 2009 Avionic Design GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Written by Thierry Reding <thierry.reding@avionic-design.de>
11 */
12
13#include <linux/backlight.h>
14#include <linux/fb.h>
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18
19/* register definitions */
20#define ADX_BACKLIGHT_CONTROL 0x00
21#define ADX_BACKLIGHT_CONTROL_ENABLE (1 << 0)
22#define ADX_BACKLIGHT_BRIGHTNESS 0x08
23#define ADX_BACKLIGHT_STATUS 0x10
24#define ADX_BACKLIGHT_ERROR 0x18
25
26struct adxbl {
27 void __iomem *base;
28};
29
30static int adx_backlight_update_status(struct backlight_device *bldev)
31{
32 struct adxbl *bl = bl_get_data(bldev);
33 u32 value;
34
35 value = bldev->props.brightness;
36 writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS);
37
38 value = readl(bl->base + ADX_BACKLIGHT_CONTROL);
39
40 if (bldev->props.state & BL_CORE_FBBLANK)
41 value &= ~ADX_BACKLIGHT_CONTROL_ENABLE;
42 else
43 value |= ADX_BACKLIGHT_CONTROL_ENABLE;
44
45 writel(value, bl->base + ADX_BACKLIGHT_CONTROL);
46
47 return 0;
48}
49
50static int adx_backlight_get_brightness(struct backlight_device *bldev)
51{
52 struct adxbl *bl = bl_get_data(bldev);
53 u32 brightness;
54
55 brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS);
56 return brightness & 0xff;
57}
58
59static int adx_backlight_check_fb(struct fb_info *fb)
60{
61 return 1;
62}
63
64static struct backlight_ops adx_backlight_ops = {
65 .options = 0,
66 .update_status = adx_backlight_update_status,
67 .get_brightness = adx_backlight_get_brightness,
68 .check_fb = adx_backlight_check_fb,
69};
70
71static int __devinit adx_backlight_probe(struct platform_device *pdev)
72{
73 struct backlight_device *bldev;
74 struct resource *res;
75 struct adxbl *bl;
76 int ret = 0;
77
78 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
79 if (!res) {
80 ret = -ENXIO;
81 goto out;
82 }
83
84 res = devm_request_mem_region(&pdev->dev, res->start,
85 resource_size(res), res->name);
86 if (!res) {
87 ret = -ENXIO;
88 goto out;
89 }
90
91 bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL);
92 if (!bl) {
93 ret = -ENOMEM;
94 goto out;
95 }
96
97 bl->base = devm_ioremap_nocache(&pdev->dev, res->start,
98 resource_size(res));
99 if (!bl->base) {
100 ret = -ENXIO;
101 goto out;
102 }
103
104 bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, bl,
105 &adx_backlight_ops);
106 if (!bldev) {
107 ret = -ENOMEM;
108 goto out;
109 }
110
111 bldev->props.max_brightness = 0xff;
112 bldev->props.brightness = 0xff;
113 bldev->props.power = FB_BLANK_UNBLANK;
114
115 platform_set_drvdata(pdev, bldev);
116
117out:
118 return ret;
119}
120
121static int __devexit adx_backlight_remove(struct platform_device *pdev)
122{
123 struct backlight_device *bldev;
124 int ret = 0;
125
126 bldev = platform_get_drvdata(pdev);
127 bldev->props.power = FB_BLANK_UNBLANK;
128 bldev->props.brightness = 0xff;
129 backlight_update_status(bldev);
130 backlight_device_unregister(bldev);
131 platform_set_drvdata(pdev, NULL);
132
133 return ret;
134}
135
136#ifdef CONFIG_PM
137static int adx_backlight_suspend(struct platform_device *pdev,
138 pm_message_t state)
139{
140 return 0;
141}
142
143static int adx_backlight_resume(struct platform_device *pdev)
144{
145 return 0;
146}
147#else
148#define adx_backlight_suspend NULL
149#define adx_backlight_resume NULL
150#endif
151
152static struct platform_driver adx_backlight_driver = {
153 .probe = adx_backlight_probe,
154 .remove = __devexit_p(adx_backlight_remove),
155 .suspend = adx_backlight_suspend,
156 .resume = adx_backlight_resume,
157 .driver = {
158 .name = "adx-backlight",
159 .owner = THIS_MODULE,
160 },
161};
162
163static int __init adx_backlight_init(void)
164{
165 return platform_driver_register(&adx_backlight_driver);
166}
167
168static void __exit adx_backlight_exit(void)
169{
170 platform_driver_unregister(&adx_backlight_driver);
171}
172
173module_init(adx_backlight_init);
174module_exit(adx_backlight_exit);
175
176MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
177MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver");
178MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 157057c79ca3..6615ac7fa60a 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -73,6 +73,27 @@ static inline void backlight_unregister_fb(struct backlight_device *bd)
73} 73}
74#endif /* CONFIG_FB */ 74#endif /* CONFIG_FB */
75 75
76static void backlight_generate_event(struct backlight_device *bd,
77 enum backlight_update_reason reason)
78{
79 char *envp[2];
80
81 switch (reason) {
82 case BACKLIGHT_UPDATE_SYSFS:
83 envp[0] = "SOURCE=sysfs";
84 break;
85 case BACKLIGHT_UPDATE_HOTKEY:
86 envp[0] = "SOURCE=hotkey";
87 break;
88 default:
89 envp[0] = "SOURCE=unknown";
90 break;
91 }
92 envp[1] = NULL;
93 kobject_uevent_env(&bd->dev.kobj, KOBJ_CHANGE, envp);
94 sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness");
95}
96
76static ssize_t backlight_show_power(struct device *dev, 97static ssize_t backlight_show_power(struct device *dev,
77 struct device_attribute *attr,char *buf) 98 struct device_attribute *attr,char *buf)
78{ 99{
@@ -142,6 +163,8 @@ static ssize_t backlight_store_brightness(struct device *dev,
142 } 163 }
143 mutex_unlock(&bd->ops_lock); 164 mutex_unlock(&bd->ops_lock);
144 165
166 backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS);
167
145 return rc; 168 return rc;
146} 169}
147 170
@@ -214,6 +237,25 @@ static struct device_attribute bl_device_attributes[] = {
214}; 237};
215 238
216/** 239/**
240 * backlight_force_update - tell the backlight subsystem that hardware state
241 * has changed
242 * @bd: the backlight device to update
243 *
244 * Updates the internal state of the backlight in response to a hardware event,
245 * and generate a uevent to notify userspace
246 */
247void backlight_force_update(struct backlight_device *bd,
248 enum backlight_update_reason reason)
249{
250 mutex_lock(&bd->ops_lock);
251 if (bd->ops && bd->ops->get_brightness)
252 bd->props.brightness = bd->ops->get_brightness(bd);
253 mutex_unlock(&bd->ops_lock);
254 backlight_generate_event(bd, reason);
255}
256EXPORT_SYMBOL(backlight_force_update);
257
258/**
217 * backlight_device_register - create and register a new object of 259 * backlight_device_register - create and register a new object of
218 * backlight_device class. 260 * backlight_device class.
219 * @name: the name of the new object(must be the same as the name of the 261 * @name: the name of the new object(must be the same as the name of the
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index f8a4bb20f41a..96774949cd30 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -433,8 +433,9 @@ static int corgi_bl_update_status(struct backlight_device *bd)
433 433
434 if (corgibl_flags & CORGIBL_SUSPENDED) 434 if (corgibl_flags & CORGIBL_SUSPENDED)
435 intensity = 0; 435 intensity = 0;
436 if (corgibl_flags & CORGIBL_BATTLOW) 436
437 intensity &= lcd->limit_mask; 437 if ((corgibl_flags & CORGIBL_BATTLOW) && intensity > lcd->limit_mask)
438 intensity = lcd->limit_mask;
438 439
439 return corgi_bl_set_intensity(lcd, intensity); 440 return corgi_bl_set_intensity(lcd, intensity);
440} 441}
@@ -639,3 +640,4 @@ module_exit(corgi_lcd_exit);
639MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00"); 640MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00");
640MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); 641MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
641MODULE_LICENSE("GPL"); 642MODULE_LICENSE("GPL");
643MODULE_ALIAS("spi:corgi-lcd");
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 93bb4340cc64..701a1081e199 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -154,34 +154,38 @@ static int da903x_backlight_remove(struct platform_device *pdev)
154} 154}
155 155
156#ifdef CONFIG_PM 156#ifdef CONFIG_PM
157static int da903x_backlight_suspend(struct platform_device *pdev, 157static int da903x_backlight_suspend(struct device *dev)
158 pm_message_t state)
159{ 158{
159 struct platform_device *pdev = to_platform_device(dev);
160 struct backlight_device *bl = platform_get_drvdata(pdev); 160 struct backlight_device *bl = platform_get_drvdata(pdev);
161 return da903x_backlight_set(bl, 0); 161 return da903x_backlight_set(bl, 0);
162} 162}
163 163
164static int da903x_backlight_resume(struct platform_device *pdev) 164static int da903x_backlight_resume(struct device *dev)
165{ 165{
166 struct platform_device *pdev = to_platform_device(dev);
166 struct backlight_device *bl = platform_get_drvdata(pdev); 167 struct backlight_device *bl = platform_get_drvdata(pdev);
167 168
168 backlight_update_status(bl); 169 backlight_update_status(bl);
169 return 0; 170 return 0;
170} 171}
171#else 172
172#define da903x_backlight_suspend NULL 173static struct dev_pm_ops da903x_backlight_pm_ops = {
173#define da903x_backlight_resume NULL 174 .suspend = da903x_backlight_suspend,
175 .resume = da903x_backlight_resume,
176};
174#endif 177#endif
175 178
176static struct platform_driver da903x_backlight_driver = { 179static struct platform_driver da903x_backlight_driver = {
177 .driver = { 180 .driver = {
178 .name = "da903x-backlight", 181 .name = "da903x-backlight",
179 .owner = THIS_MODULE, 182 .owner = THIS_MODULE,
183#ifdef CONFIG_PM
184 .pm = &da903x_backlight_pm_ops,
185#endif
180 }, 186 },
181 .probe = da903x_backlight_probe, 187 .probe = da903x_backlight_probe,
182 .remove = da903x_backlight_remove, 188 .remove = da903x_backlight_remove,
183 .suspend = da903x_backlight_suspend,
184 .resume = da903x_backlight_resume,
185}; 189};
186 190
187static int __init da903x_backlight_init(void) 191static int __init da903x_backlight_init(void)
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 5be55a20d8c7..7fb4eefff80d 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -103,7 +103,7 @@ static struct backlight_ops hp680bl_ops = {
103 .update_status = hp680bl_set_intensity, 103 .update_status = hp680bl_set_intensity,
104}; 104};
105 105
106static int __init hp680bl_probe(struct platform_device *pdev) 106static int __devinit hp680bl_probe(struct platform_device *pdev)
107{ 107{
108 struct backlight_device *bd; 108 struct backlight_device *bd;
109 109
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index c3ebb6b41ce1..7aed2565c1bd 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -72,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
72 if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) { 72 if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
73 printk(KERN_INFO "bl : failed to set brightness\n"); 73 printk(KERN_INFO "bl : failed to set brightness\n");
74 ret = -ETIMEDOUT; 74 ret = -ETIMEDOUT;
75 goto out 75 goto out;
76 } 76 }
77 77
78 /* at this point we expect that the mcu has accepted 78 /* at this point we expect that the mcu has accepted
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index b6449470106c..a482dd7b0311 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -56,7 +56,7 @@ static int fb_notifier_callback(struct notifier_block *self,
56 56
57static int lcd_register_fb(struct lcd_device *ld) 57static int lcd_register_fb(struct lcd_device *ld)
58{ 58{
59 memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif)); 59 memset(&ld->fb_notif, 0, sizeof(ld->fb_notif));
60 ld->fb_notif.notifier_call = fb_notifier_callback; 60 ld->fb_notif.notifier_call = fb_notifier_callback;
61 return fb_register_client(&ld->fb_notif); 61 return fb_register_client(&ld->fb_notif);
62} 62}
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
new file mode 100644
index 000000000000..447b542a20ca
--- /dev/null
+++ b/drivers/video/backlight/lms283gf05.c
@@ -0,0 +1,242 @@
1/*
2 * lms283gf05.c -- support for Samsung LMS283GF05 LCD
3 *
4 * Copyright (c) 2009 Marek Vasut <marek.vasut@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/device.h>
12#include <linux/kernel.h>
13#include <linux/delay.h>
14#include <linux/gpio.h>
15#include <linux/lcd.h>
16
17#include <linux/spi/spi.h>
18#include <linux/spi/lms283gf05.h>
19
20struct lms283gf05_state {
21 struct spi_device *spi;
22 struct lcd_device *ld;
23};
24
25struct lms283gf05_seq {
26 unsigned char reg;
27 unsigned short value;
28 unsigned char delay;
29};
30
31/* Magic sequences supplied by manufacturer, for details refer to datasheet */
32static struct lms283gf05_seq disp_initseq[] = {
33 /* REG, VALUE, DELAY */
34 { 0x07, 0x0000, 0 },
35 { 0x13, 0x0000, 10 },
36
37 { 0x11, 0x3004, 0 },
38 { 0x14, 0x200F, 0 },
39 { 0x10, 0x1a20, 0 },
40 { 0x13, 0x0040, 50 },
41
42 { 0x13, 0x0060, 0 },
43 { 0x13, 0x0070, 200 },
44
45 { 0x01, 0x0127, 0 },
46 { 0x02, 0x0700, 0 },
47 { 0x03, 0x1030, 0 },
48 { 0x08, 0x0208, 0 },
49 { 0x0B, 0x0620, 0 },
50 { 0x0C, 0x0110, 0 },
51 { 0x30, 0x0120, 0 },
52 { 0x31, 0x0127, 0 },
53 { 0x32, 0x0000, 0 },
54 { 0x33, 0x0503, 0 },
55 { 0x34, 0x0727, 0 },
56 { 0x35, 0x0124, 0 },
57 { 0x36, 0x0706, 0 },
58 { 0x37, 0x0701, 0 },
59 { 0x38, 0x0F00, 0 },
60 { 0x39, 0x0F00, 0 },
61 { 0x40, 0x0000, 0 },
62 { 0x41, 0x0000, 0 },
63 { 0x42, 0x013f, 0 },
64 { 0x43, 0x0000, 0 },
65 { 0x44, 0x013f, 0 },
66 { 0x45, 0x0000, 0 },
67 { 0x46, 0xef00, 0 },
68 { 0x47, 0x013f, 0 },
69 { 0x48, 0x0000, 0 },
70 { 0x07, 0x0015, 30 },
71
72 { 0x07, 0x0017, 0 },
73
74 { 0x20, 0x0000, 0 },
75 { 0x21, 0x0000, 0 },
76 { 0x22, 0x0000, 0 }
77};
78
79static struct lms283gf05_seq disp_pdwnseq[] = {
80 { 0x07, 0x0016, 30 },
81
82 { 0x07, 0x0004, 0 },
83 { 0x10, 0x0220, 20 },
84
85 { 0x13, 0x0060, 50 },
86
87 { 0x13, 0x0040, 50 },
88
89 { 0x13, 0x0000, 0 },
90 { 0x10, 0x0000, 0 }
91};
92
93
94static void lms283gf05_reset(unsigned long gpio, bool inverted)
95{
96 gpio_set_value(gpio, !inverted);
97 mdelay(100);
98 gpio_set_value(gpio, inverted);
99 mdelay(20);
100 gpio_set_value(gpio, !inverted);
101 mdelay(20);
102}
103
104static void lms283gf05_toggle(struct spi_device *spi,
105 struct lms283gf05_seq *seq, int sz)
106{
107 char buf[3];
108 int i;
109
110 for (i = 0; i < sz; i++) {
111 buf[0] = 0x74;
112 buf[1] = 0x00;
113 buf[2] = seq[i].reg;
114 spi_write(spi, buf, 3);
115
116 buf[0] = 0x76;
117 buf[1] = seq[i].value >> 8;
118 buf[2] = seq[i].value & 0xff;
119 spi_write(spi, buf, 3);
120
121 mdelay(seq[i].delay);
122 }
123}
124
125static int lms283gf05_power_set(struct lcd_device *ld, int power)
126{
127 struct lms283gf05_state *st = lcd_get_data(ld);
128 struct spi_device *spi = st->spi;
129 struct lms283gf05_pdata *pdata = spi->dev.platform_data;
130
131 if (power) {
132 if (pdata)
133 lms283gf05_reset(pdata->reset_gpio,
134 pdata->reset_inverted);
135 lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq));
136 } else {
137 lms283gf05_toggle(spi, disp_pdwnseq, ARRAY_SIZE(disp_pdwnseq));
138 if (pdata)
139 gpio_set_value(pdata->reset_gpio,
140 pdata->reset_inverted);
141 }
142
143 return 0;
144}
145
146static struct lcd_ops lms_ops = {
147 .set_power = lms283gf05_power_set,
148 .get_power = NULL,
149};
150
151static int __devinit lms283gf05_probe(struct spi_device *spi)
152{
153 struct lms283gf05_state *st;
154 struct lms283gf05_pdata *pdata = spi->dev.platform_data;
155 struct lcd_device *ld;
156 int ret = 0;
157
158 if (pdata != NULL) {
159 ret = gpio_request(pdata->reset_gpio, "LMS285GF05 RESET");
160 if (ret)
161 return ret;
162
163 ret = gpio_direction_output(pdata->reset_gpio,
164 !pdata->reset_inverted);
165 if (ret)
166 goto err;
167 }
168
169 st = kzalloc(sizeof(struct lms283gf05_state), GFP_KERNEL);
170 if (st == NULL) {
171 dev_err(&spi->dev, "No memory for device state\n");
172 ret = -ENOMEM;
173 goto err;
174 }
175
176 ld = lcd_device_register("lms283gf05", &spi->dev, st, &lms_ops);
177 if (IS_ERR(ld)) {
178 ret = PTR_ERR(ld);
179 goto err2;
180 }
181
182 st->spi = spi;
183 st->ld = ld;
184
185 dev_set_drvdata(&spi->dev, st);
186
187 /* kick in the LCD */
188 if (pdata)
189 lms283gf05_reset(pdata->reset_gpio, pdata->reset_inverted);
190 lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq));
191
192 return 0;
193
194err2:
195 kfree(st);
196err:
197 if (pdata != NULL)
198 gpio_free(pdata->reset_gpio);
199
200 return ret;
201}
202
203static int __devexit lms283gf05_remove(struct spi_device *spi)
204{
205 struct lms283gf05_state *st = dev_get_drvdata(&spi->dev);
206 struct lms283gf05_pdata *pdata = st->spi->dev.platform_data;
207
208 lcd_device_unregister(st->ld);
209
210 if (pdata != NULL)
211 gpio_free(pdata->reset_gpio);
212
213 kfree(st);
214
215 return 0;
216}
217
218static struct spi_driver lms283gf05_driver = {
219 .driver = {
220 .name = "lms283gf05",
221 .owner = THIS_MODULE,
222 },
223 .probe = lms283gf05_probe,
224 .remove = __devexit_p(lms283gf05_remove),
225};
226
227static __init int lms283gf05_init(void)
228{
229 return spi_register_driver(&lms283gf05_driver);
230}
231
232static __exit void lms283gf05_exit(void)
233{
234 spi_unregister_driver(&lms283gf05_driver);
235}
236
237module_init(lms283gf05_init);
238module_exit(lms283gf05_exit);
239
240MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
241MODULE_DESCRIPTION("LCD283GF05 LCD");
242MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 2eb206bf73e6..4631ca8fa4a4 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -328,3 +328,4 @@ module_exit(ltv350qv_exit);
328MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); 328MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
329MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver"); 329MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver");
330MODULE_LICENSE("GPL"); 330MODULE_LICENSE("GPL");
331MODULE_ALIAS("spi:ltv350qv");
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 3bb4c0a50c62..9edb8d7c295f 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -166,6 +166,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
166 }, 166 },
167 { 167 {
168 .callback = mbp_dmi_match, 168 .callback = mbp_dmi_match,
169 .ident = "MacBookAir 1,1",
170 .matches = {
171 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
172 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir1,1"),
173 },
174 .driver_data = (void *)&intel_chipset_data,
175 },
176 {
177 .callback = mbp_dmi_match,
169 .ident = "MacBook 5,1", 178 .ident = "MacBook 5,1",
170 .matches = { 179 .matches = {
171 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 180 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -175,6 +184,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
175 }, 184 },
176 { 185 {
177 .callback = mbp_dmi_match, 186 .callback = mbp_dmi_match,
187 .ident = "MacBook 5,2",
188 .matches = {
189 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
190 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"),
191 },
192 .driver_data = (void *)&nvidia_chipset_data,
193 },
194 {
195 .callback = mbp_dmi_match,
178 .ident = "MacBookAir 2,1", 196 .ident = "MacBookAir 2,1",
179 .matches = { 197 .matches = {
180 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 198 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -191,6 +209,24 @@ static const struct dmi_system_id __initdata mbp_device_table[] = {
191 }, 209 },
192 .driver_data = (void *)&nvidia_chipset_data, 210 .driver_data = (void *)&nvidia_chipset_data,
193 }, 211 },
212 {
213 .callback = mbp_dmi_match,
214 .ident = "MacBookPro 5,2",
215 .matches = {
216 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
217 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"),
218 },
219 .driver_data = (void *)&nvidia_chipset_data,
220 },
221 {
222 .callback = mbp_dmi_match,
223 .ident = "MacBookPro 5,5",
224 .matches = {
225 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
226 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"),
227 },
228 .driver_data = (void *)&nvidia_chipset_data,
229 },
194 { } 230 { }
195}; 231};
196 232
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index e641584e212e..887166267443 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -145,6 +145,8 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
145 struct backlight_device *bl = platform_get_drvdata(pdev); 145 struct backlight_device *bl = platform_get_drvdata(pdev);
146 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); 146 struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
147 147
148 if (pb->notify)
149 pb->notify(0);
148 pwm_config(pb->pwm, 0, pb->period); 150 pwm_config(pb->pwm, 0, pb->period);
149 pwm_disable(pb->pwm); 151 pwm_disable(pb->pwm);
150 return 0; 152 return 0;
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 1dae7f8f3c6b..bbfb502add67 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -356,7 +356,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
356 lcd->power = FB_BLANK_POWERDOWN; 356 lcd->power = FB_BLANK_POWERDOWN;
357 lcd->mode = MODE_VGA; /* default to VGA */ 357 lcd->mode = MODE_VGA; /* default to VGA */
358 358
359 lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL)); 359 lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
360 if (lcd->buf == NULL) { 360 if (lcd->buf == NULL) {
361 kfree(lcd); 361 kfree(lcd);
362 return -ENOMEM; 362 return -ENOMEM;
@@ -472,3 +472,4 @@ module_exit(tdo24m_exit);
472MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); 472MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
473MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel"); 473MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel");
474MODULE_LICENSE("GPL"); 474MODULE_LICENSE("GPL");
475MODULE_ALIAS("spi:tdo24m");
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index b7fbc75a62fc..50ec17dfc517 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -300,4 +300,4 @@ module_exit(tosa_lcd_exit);
300MODULE_AUTHOR("Dmitry Baryshkov"); 300MODULE_AUTHOR("Dmitry Baryshkov");
301MODULE_LICENSE("GPL v2"); 301MODULE_LICENSE("GPL v2");
302MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA"); 302MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");
303 303MODULE_ALIAS("spi:tosa-lcd");
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index 8e653b8a6f17..b49063c831e7 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -280,5 +280,4 @@ module_exit(vgg2432a4_exit);
280MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); 280MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
281MODULE_DESCRIPTION("VGG2432A4 LCD Driver"); 281MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
282MODULE_LICENSE("GPL v2"); 282MODULE_LICENSE("GPL v2");
283 283MODULE_ALIAS("spi:VGG2432A4");
284
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
new file mode 100644
index 000000000000..467bdb7efb23
--- /dev/null
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -0,0 +1,250 @@
1/*
2 * Backlight driver for Wolfson Microelectronics WM831x PMICs
3 *
4 * Copyright 2009 Wolfson Microelectonics plc
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/platform_device.h>
14#include <linux/fb.h>
15#include <linux/backlight.h>
16
17#include <linux/mfd/wm831x/core.h>
18#include <linux/mfd/wm831x/pdata.h>
19#include <linux/mfd/wm831x/regulator.h>
20
21struct wm831x_backlight_data {
22 struct wm831x *wm831x;
23 int isink_reg;
24 int current_brightness;
25};
26
27static int wm831x_backlight_set(struct backlight_device *bl, int brightness)
28{
29 struct wm831x_backlight_data *data = bl_get_data(bl);
30 struct wm831x *wm831x = data->wm831x;
31 int power_up = !data->current_brightness && brightness;
32 int power_down = data->current_brightness && !brightness;
33 int ret;
34
35 if (power_up) {
36 /* Enable the ISINK */
37 ret = wm831x_set_bits(wm831x, data->isink_reg,
38 WM831X_CS1_ENA, WM831X_CS1_ENA);
39 if (ret < 0)
40 goto err;
41
42 /* Enable the DC-DC */
43 ret = wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE,
44 WM831X_DC4_ENA, WM831X_DC4_ENA);
45 if (ret < 0)
46 goto err;
47 }
48
49 if (power_down) {
50 /* DCDC first */
51 ret = wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE,
52 WM831X_DC4_ENA, 0);
53 if (ret < 0)
54 goto err;
55
56 /* ISINK */
57 ret = wm831x_set_bits(wm831x, data->isink_reg,
58 WM831X_CS1_DRIVE | WM831X_CS1_ENA, 0);
59 if (ret < 0)
60 goto err;
61 }
62
63 /* Set the new brightness */
64 ret = wm831x_set_bits(wm831x, data->isink_reg,
65 WM831X_CS1_ISEL_MASK, brightness);
66 if (ret < 0)
67 goto err;
68
69 if (power_up) {
70 /* Drive current through the ISINK */
71 ret = wm831x_set_bits(wm831x, data->isink_reg,
72 WM831X_CS1_DRIVE, WM831X_CS1_DRIVE);
73 if (ret < 0)
74 return ret;
75 }
76
77 data->current_brightness = brightness;
78
79 return 0;
80
81err:
82 /* If we were in the middle of a power transition always shut down
83 * for safety.
84 */
85 if (power_up || power_down) {
86 wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, WM831X_DC4_ENA, 0);
87 wm831x_set_bits(wm831x, data->isink_reg, WM831X_CS1_ENA, 0);
88 }
89
90 return ret;
91}
92
93static int wm831x_backlight_update_status(struct backlight_device *bl)
94{
95 int brightness = bl->props.brightness;
96
97 if (bl->props.power != FB_BLANK_UNBLANK)
98 brightness = 0;
99
100 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
101 brightness = 0;
102
103 if (bl->props.state & BL_CORE_SUSPENDED)
104 brightness = 0;
105
106 return wm831x_backlight_set(bl, brightness);
107}
108
109static int wm831x_backlight_get_brightness(struct backlight_device *bl)
110{
111 struct wm831x_backlight_data *data = bl_get_data(bl);
112 return data->current_brightness;
113}
114
115static struct backlight_ops wm831x_backlight_ops = {
116 .options = BL_CORE_SUSPENDRESUME,
117 .update_status = wm831x_backlight_update_status,
118 .get_brightness = wm831x_backlight_get_brightness,
119};
120
121static int wm831x_backlight_probe(struct platform_device *pdev)
122{
123 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
124 struct wm831x_pdata *wm831x_pdata;
125 struct wm831x_backlight_pdata *pdata;
126 struct wm831x_backlight_data *data;
127 struct backlight_device *bl;
128 int ret, i, max_isel, isink_reg, dcdc_cfg;
129
130 /* We need platform data */
131 if (pdev->dev.parent->platform_data) {
132 wm831x_pdata = pdev->dev.parent->platform_data;
133 pdata = wm831x_pdata->backlight;
134 } else {
135 pdata = NULL;
136 }
137
138 if (!pdata) {
139 dev_err(&pdev->dev, "No platform data supplied\n");
140 return -EINVAL;
141 }
142
143 /* Figure out the maximum current we can use */
144 for (i = 0; i < WM831X_ISINK_MAX_ISEL; i++) {
145 if (wm831x_isinkv_values[i] > pdata->max_uA)
146 break;
147 }
148
149 if (i == 0) {
150 dev_err(&pdev->dev, "Invalid max_uA: %duA\n", pdata->max_uA);
151 return -EINVAL;
152 }
153 max_isel = i - 1;
154
155 if (pdata->max_uA != wm831x_isinkv_values[max_isel])
156 dev_warn(&pdev->dev,
157 "Maximum current is %duA not %duA as requested\n",
158 wm831x_isinkv_values[max_isel], pdata->max_uA);
159
160 switch (pdata->isink) {
161 case 1:
162 isink_reg = WM831X_CURRENT_SINK_1;
163 dcdc_cfg = 0;
164 break;
165 case 2:
166 isink_reg = WM831X_CURRENT_SINK_2;
167 dcdc_cfg = WM831X_DC4_FBSRC;
168 break;
169 default:
170 dev_err(&pdev->dev, "Invalid ISINK %d\n", pdata->isink);
171 return -EINVAL;
172 }
173
174 /* Configure the ISINK to use for feedback */
175 ret = wm831x_reg_unlock(wm831x);
176 if (ret < 0)
177 return ret;
178
179 ret = wm831x_set_bits(wm831x, WM831X_DC4_CONTROL, WM831X_DC4_FBSRC,
180 dcdc_cfg);
181
182 wm831x_reg_lock(wm831x);
183 if (ret < 0)
184 return ret;
185
186 data = kzalloc(sizeof(*data), GFP_KERNEL);
187 if (data == NULL)
188 return -ENOMEM;
189
190 data->wm831x = wm831x;
191 data->current_brightness = 0;
192 data->isink_reg = isink_reg;
193
194 bl = backlight_device_register("wm831x", &pdev->dev,
195 data, &wm831x_backlight_ops);
196 if (IS_ERR(bl)) {
197 dev_err(&pdev->dev, "failed to register backlight\n");
198 kfree(data);
199 return PTR_ERR(bl);
200 }
201
202 bl->props.max_brightness = max_isel;
203 bl->props.brightness = max_isel;
204
205 platform_set_drvdata(pdev, bl);
206
207 /* Disable the DCDC if it was started so we can bootstrap */
208 wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, WM831X_DC4_ENA, 0);
209
210
211 backlight_update_status(bl);
212
213 return 0;
214}
215
216static int wm831x_backlight_remove(struct platform_device *pdev)
217{
218 struct backlight_device *bl = platform_get_drvdata(pdev);
219 struct wm831x_backlight_data *data = bl_get_data(bl);
220
221 backlight_device_unregister(bl);
222 kfree(data);
223 return 0;
224}
225
226static struct platform_driver wm831x_backlight_driver = {
227 .driver = {
228 .name = "wm831x-backlight",
229 .owner = THIS_MODULE,
230 },
231 .probe = wm831x_backlight_probe,
232 .remove = wm831x_backlight_remove,
233};
234
235static int __init wm831x_backlight_init(void)
236{
237 return platform_driver_register(&wm831x_backlight_driver);
238}
239module_init(wm831x_backlight_init);
240
241static void __exit wm831x_backlight_exit(void)
242{
243 platform_driver_unregister(&wm831x_backlight_driver);
244}
245module_exit(wm831x_backlight_exit);
246
247MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs");
248MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com");
249MODULE_LICENSE("GPL");
250MODULE_ALIAS("platform:wm831x-backlight");
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index df03f3776dcc..79e5f40e6486 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -114,7 +114,7 @@ bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
114 d0 >>= right; 114 d0 >>= right;
115 } else if (src_idx+n <= bits) { 115 } else if (src_idx+n <= bits) {
116 // Single source word 116 // Single source word
117 d0 <<= left;; 117 d0 <<= left;
118 } else { 118 } else {
119 // 2 source words 119 // 2 source words
120 d1 = FB_READL(src + 1); 120 d1 = FB_READL(src + 1);
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 7bad24ed04ef..108b89e09a80 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Cobalt server LCD frame buffer driver. 2 * Cobalt server LCD frame buffer driver.
3 * 3 *
4 * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 4 * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/video/console/.gitignore b/drivers/video/console/.gitignore
deleted file mode 100644
index 0c258b45439c..000000000000
--- a/drivers/video/console/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1# conmakehash generated file
2promcon_tbl.c
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 2f50a80b413e..fc7d9bbb548c 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -67,16 +67,9 @@ config SGI_NEWPORT_CONSOLE
67 67
68# bool 'IODC console' CONFIG_IODC_CONSOLE 68# bool 'IODC console' CONFIG_IODC_CONSOLE
69 69
70config PROM_CONSOLE
71 bool "PROM console"
72 depends on SPARC
73 help
74 Say Y to build a console driver for Sun machines that uses the
75 terminal emulation built into their console PROMS.
76
77config DUMMY_CONSOLE 70config DUMMY_CONSOLE
78 bool 71 bool
79 depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y 72 depends on VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
80 default y 73 default y
81 74
82config DUMMY_CONSOLE_COLUMNS 75config DUMMY_CONSOLE_COLUMNS
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index ac46cc3f6a2a..a862e9173ebe 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -22,7 +22,6 @@ font-objs += $(font-objs-y)
22 22
23obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o 23obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
24obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o 24obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
25obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
26obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o 25obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
27obj-$(CONFIG_VGA_CONSOLE) += vgacon.o 26obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
28obj-$(CONFIG_MDA_CONSOLE) += mdacon.o 27obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
@@ -40,14 +39,3 @@ obj-$(CONFIG_FB_STI) += sticore.o font.o
40ifeq ($(CONFIG_USB_SISUSBVGA_CON),y) 39ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
41obj-$(CONFIG_USB_SISUSBVGA) += font.o 40obj-$(CONFIG_USB_SISUSBVGA) += font.o
42endif 41endif
43
44# Targets that kbuild needs to know about
45targets := promcon_tbl.c
46
47quiet_cmd_conmakehash = CNMKHSH $@
48 cmd_conmakehash = scripts/conmakehash $< | \
49 sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \
50 -e 's/dfont\(_uni.*\]\)/promfont\1 /' > $@
51
52$(obj)/promcon_tbl.c: $(src)/prom.uni
53 $(call cmd,conmakehash)
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 69864b1b3f9e..6b7c8fbc5495 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -25,7 +25,7 @@ static inline void update_attr(u8 *dst, u8 *src, int attribute,
25 struct vc_data *vc) 25 struct vc_data *vc)
26{ 26{
27 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 27 int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
28 int width = (vc->vc_font.width + 7) >> 3; 28 int width = DIV_ROUND_UP(vc->vc_font.width, 8);
29 unsigned int cellsize = vc->vc_font.height * width; 29 unsigned int cellsize = vc->vc_font.height * width;
30 u8 c; 30 u8 c;
31 31
@@ -144,7 +144,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
144 int fg, int bg) 144 int fg, int bg)
145{ 145{
146 struct fb_image image; 146 struct fb_image image;
147 u32 width = (vc->vc_font.width + 7)/8; 147 u32 width = DIV_ROUND_UP(vc->vc_font.width, 8);
148 u32 cellsize = width * vc->vc_font.height; 148 u32 cellsize = width * vc->vc_font.height;
149 u32 maxcnt = info->pixmap.size/cellsize; 149 u32 maxcnt = info->pixmap.size/cellsize;
150 u32 scan_align = info->pixmap.scan_align - 1; 150 u32 scan_align = info->pixmap.scan_align - 1;
@@ -173,7 +173,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
173 cnt = count; 173 cnt = count;
174 174
175 image.width = vc->vc_font.width * cnt; 175 image.width = vc->vc_font.width * cnt;
176 pitch = ((image.width + 7) >> 3) + scan_align; 176 pitch = DIV_ROUND_UP(image.width, 8) + scan_align;
177 pitch &= ~scan_align; 177 pitch &= ~scan_align;
178 size = pitch * image.height + buf_align; 178 size = pitch * image.height + buf_align;
179 size &= ~buf_align; 179 size &= ~buf_align;
@@ -239,7 +239,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
239 struct fb_cursor cursor; 239 struct fb_cursor cursor;
240 struct fbcon_ops *ops = info->fbcon_par; 240 struct fbcon_ops *ops = info->fbcon_par;
241 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 241 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
242 int w = (vc->vc_font.width + 7) >> 3, c; 242 int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
243 int y = real_y(ops->p, vc->vc_y); 243 int y = real_y(ops->p, vc->vc_y);
244 int attribute, use_sw = (vc->vc_cursor_type & 0x10); 244 int attribute, use_sw = (vc->vc_cursor_type & 0x10);
245 int err = 1; 245 int err = 1;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 471a9a60376a..3681c6a88212 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -114,6 +114,7 @@ static int last_fb_vc = MAX_NR_CONSOLES - 1;
114static int fbcon_is_default = 1; 114static int fbcon_is_default = 1;
115static int fbcon_has_exited; 115static int fbcon_has_exited;
116static int primary_device = -1; 116static int primary_device = -1;
117static int fbcon_has_console_bind;
117 118
118#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY 119#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
119static int map_override; 120static int map_override;
@@ -544,6 +545,8 @@ static int fbcon_takeover(int show_logo)
544 con2fb_map[i] = -1; 545 con2fb_map[i] = -1;
545 } 546 }
546 info_idx = -1; 547 info_idx = -1;
548 } else {
549 fbcon_has_console_bind = 1;
547 } 550 }
548 551
549 return err; 552 return err;
@@ -725,7 +728,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
725 int oldidx, int found) 728 int oldidx, int found)
726{ 729{
727 struct fbcon_ops *ops = oldinfo->fbcon_par; 730 struct fbcon_ops *ops = oldinfo->fbcon_par;
728 int err = 0; 731 int err = 0, ret;
729 732
730 if (oldinfo->fbops->fb_release && 733 if (oldinfo->fbops->fb_release &&
731 oldinfo->fbops->fb_release(oldinfo, 0)) { 734 oldinfo->fbops->fb_release(oldinfo, 0)) {
@@ -752,8 +755,14 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
752 newinfo in an undefined state. Thus, a call to 755 newinfo in an undefined state. Thus, a call to
753 fb_set_par() may be needed for the newinfo. 756 fb_set_par() may be needed for the newinfo.
754 */ 757 */
755 if (newinfo->fbops->fb_set_par) 758 if (newinfo->fbops->fb_set_par) {
756 newinfo->fbops->fb_set_par(newinfo); 759 ret = newinfo->fbops->fb_set_par(newinfo);
760
761 if (ret)
762 printk(KERN_ERR "con2fb_release_oldinfo: "
763 "detected unhandled fb_set_par error, "
764 "error code %d\n", ret);
765 }
757 } 766 }
758 767
759 return err; 768 return err;
@@ -763,11 +772,18 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
763 int unit, int show_logo) 772 int unit, int show_logo)
764{ 773{
765 struct fbcon_ops *ops = info->fbcon_par; 774 struct fbcon_ops *ops = info->fbcon_par;
775 int ret;
766 776
767 ops->currcon = fg_console; 777 ops->currcon = fg_console;
768 778
769 if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) 779 if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) {
770 info->fbops->fb_set_par(info); 780 ret = info->fbops->fb_set_par(info);
781
782 if (ret)
783 printk(KERN_ERR "con2fb_init_display: detected "
784 "unhandled fb_set_par error, "
785 "error code %d\n", ret);
786 }
771 787
772 ops->flags |= FBCON_FLAGS_INIT; 788 ops->flags |= FBCON_FLAGS_INIT;
773 ops->graphics = 0; 789 ops->graphics = 0;
@@ -1006,7 +1022,7 @@ static void fbcon_init(struct vc_data *vc, int init)
1006 struct vc_data *svc = *default_mode; 1022 struct vc_data *svc = *default_mode;
1007 struct display *t, *p = &fb_display[vc->vc_num]; 1023 struct display *t, *p = &fb_display[vc->vc_num];
1008 int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; 1024 int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
1009 int cap; 1025 int cap, ret;
1010 1026
1011 if (info_idx == -1 || info == NULL) 1027 if (info_idx == -1 || info == NULL)
1012 return; 1028 return;
@@ -1082,7 +1098,6 @@ static void fbcon_init(struct vc_data *vc, int init)
1082 new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); 1098 new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
1083 new_cols /= vc->vc_font.width; 1099 new_cols /= vc->vc_font.width;
1084 new_rows /= vc->vc_font.height; 1100 new_rows /= vc->vc_font.height;
1085 vc_resize(vc, new_cols, new_rows);
1086 1101
1087 /* 1102 /*
1088 * We must always set the mode. The mode of the previous console 1103 * We must always set the mode. The mode of the previous console
@@ -1093,8 +1108,15 @@ static void fbcon_init(struct vc_data *vc, int init)
1093 */ 1108 */
1094 if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { 1109 if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
1095 if (info->fbops->fb_set_par && 1110 if (info->fbops->fb_set_par &&
1096 !(ops->flags & FBCON_FLAGS_INIT)) 1111 !(ops->flags & FBCON_FLAGS_INIT)) {
1097 info->fbops->fb_set_par(info); 1112 ret = info->fbops->fb_set_par(info);
1113
1114 if (ret)
1115 printk(KERN_ERR "fbcon_init: detected "
1116 "unhandled fb_set_par error, "
1117 "error code %d\n", ret);
1118 }
1119
1098 ops->flags |= FBCON_FLAGS_INIT; 1120 ops->flags |= FBCON_FLAGS_INIT;
1099 } 1121 }
1100 1122
@@ -1111,10 +1133,11 @@ static void fbcon_init(struct vc_data *vc, int init)
1111 * vc_{cols,rows}, but we must not set those if we are only 1133 * vc_{cols,rows}, but we must not set those if we are only
1112 * resizing the console. 1134 * resizing the console.
1113 */ 1135 */
1114 if (!init) { 1136 if (init) {
1115 vc->vc_cols = new_cols; 1137 vc->vc_cols = new_cols;
1116 vc->vc_rows = new_rows; 1138 vc->vc_rows = new_rows;
1117 } 1139 } else
1140 vc_resize(vc, new_cols, new_rows);
1118 1141
1119 if (logo) 1142 if (logo)
1120 fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); 1143 fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
@@ -2119,7 +2142,7 @@ static int fbcon_switch(struct vc_data *vc)
2119 struct fbcon_ops *ops; 2142 struct fbcon_ops *ops;
2120 struct display *p = &fb_display[vc->vc_num]; 2143 struct display *p = &fb_display[vc->vc_num];
2121 struct fb_var_screeninfo var; 2144 struct fb_var_screeninfo var;
2122 int i, prev_console, charcnt = 256; 2145 int i, ret, prev_console, charcnt = 256;
2123 2146
2124 info = registered_fb[con2fb_map[vc->vc_num]]; 2147 info = registered_fb[con2fb_map[vc->vc_num]];
2125 ops = info->fbcon_par; 2148 ops = info->fbcon_par;
@@ -2174,8 +2197,14 @@ static int fbcon_switch(struct vc_data *vc)
2174 2197
2175 if (old_info != NULL && (old_info != info || 2198 if (old_info != NULL && (old_info != info ||
2176 info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { 2199 info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
2177 if (info->fbops->fb_set_par) 2200 if (info->fbops->fb_set_par) {
2178 info->fbops->fb_set_par(info); 2201 ret = info->fbops->fb_set_par(info);
2202
2203 if (ret)
2204 printk(KERN_ERR "fbcon_switch: detected "
2205 "unhandled fb_set_par error, "
2206 "error code %d\n", ret);
2207 }
2179 2208
2180 if (old_info != info) 2209 if (old_info != info)
2181 fbcon_del_cursor_timer(old_info); 2210 fbcon_del_cursor_timer(old_info);
@@ -2282,14 +2311,11 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
2282 ops->graphics = 1; 2311 ops->graphics = 1;
2283 2312
2284 if (!blank) { 2313 if (!blank) {
2285 if (info->fbops->fb_save_state)
2286 info->fbops->fb_save_state(info);
2287 var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; 2314 var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
2288 fb_set_var(info, &var); 2315 fb_set_var(info, &var);
2289 ops->graphics = 0; 2316 ops->graphics = 0;
2290 ops->var = info->var; 2317 ops->var = info->var;
2291 } else if (info->fbops->fb_restore_state) 2318 }
2292 info->fbops->fb_restore_state(info);
2293 } 2319 }
2294 2320
2295 if (!fbcon_is_inactive(vc, info)) { 2321 if (!fbcon_is_inactive(vc, info)) {
@@ -2923,6 +2949,10 @@ static int fbcon_unbind(void)
2923 2949
2924 ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, 2950 ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
2925 fbcon_is_default); 2951 fbcon_is_default);
2952
2953 if (!ret)
2954 fbcon_has_console_bind = 0;
2955
2926 return ret; 2956 return ret;
2927} 2957}
2928#else 2958#else
@@ -2936,6 +2966,9 @@ static int fbcon_fb_unbind(int idx)
2936{ 2966{
2937 int i, new_idx = -1, ret = 0; 2967 int i, new_idx = -1, ret = 0;
2938 2968
2969 if (!fbcon_has_console_bind)
2970 return 0;
2971
2939 for (i = first_fb_vc; i <= last_fb_vc; i++) { 2972 for (i = first_fb_vc; i <= last_fb_vc; i++) {
2940 if (con2fb_map[i] != idx && 2973 if (con2fb_map[i] != idx &&
2941 con2fb_map[i] != -1) { 2974 con2fb_map[i] != -1) {
diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h
index 75be5ce53dc5..e233444cda66 100644
--- a/drivers/video/console/fbcon_rotate.h
+++ b/drivers/video/console/fbcon_rotate.h
@@ -45,7 +45,7 @@ static inline void rotate_ud(const char *in, char *out, u32 width, u32 height)
45 width = (width + 7) & ~7; 45 width = (width + 7) & ~7;
46 46
47 for (i = 0; i < height; i++) { 47 for (i = 0; i < height; i++) {
48 for (j = 0; j < width; j++) { 48 for (j = 0; j < width - shift; j++) {
49 if (pattern_test_bit(j, i, width, in)) 49 if (pattern_test_bit(j, i, width, in))
50 pattern_set_bit(width - (1 + j + shift), 50 pattern_set_bit(width - (1 + j + shift),
51 height - (1 + i), 51 height - (1 + i),
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index d31b203bf654..3772433c49d1 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -216,7 +216,7 @@ static void newport_get_screensize(void)
216 } 216 }
217 217
218 newport_xsize = newport_ysize = 0; 218 newport_xsize = newport_ysize = 0;
219 for (i = 0; linetable[i + 1] && (i < sizeof(linetable)); i += 2) { 219 for (i = 0; i < ARRAY_SIZE(linetable) - 1 && linetable[i + 1]; i += 2) {
220 cols = 0; 220 cols = 0;
221 newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]); 221 newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]);
222 npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | 222 npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
diff --git a/drivers/video/console/prom.uni b/drivers/video/console/prom.uni
deleted file mode 100644
index 58f9c04ed9d3..000000000000
--- a/drivers/video/console/prom.uni
+++ /dev/null
@@ -1,11 +0,0 @@
1#
2# Unicode mapping table for font in Sun PROM
3#
4#
50x20-0x7e idem
60xa0-0xff idem
7#
80x7c U+2502
90x2d U+2500
100x2b U+250c U+2510 U+2514 U+2518 U+251c U+2524 U+252c U+2534 U+253c
110xa4 U+fffd
diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c
deleted file mode 100644
index ae02e4eb18e7..000000000000
--- a/drivers/video/console/promcon.c
+++ /dev/null
@@ -1,598 +0,0 @@
1/* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 davem Exp $
2 * Console driver utilizing PROM sun terminal emulation
3 *
4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
5 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
6 */
7
8#include <linux/module.h>
9#include <linux/kernel.h>
10#include <linux/errno.h>
11#include <linux/string.h>
12#include <linux/mm.h>
13#include <linux/slab.h>
14#include <linux/delay.h>
15#include <linux/console.h>
16#include <linux/vt_kern.h>
17#include <linux/selection.h>
18#include <linux/fb.h>
19#include <linux/init.h>
20#include <linux/kd.h>
21
22#include <asm/oplib.h>
23#include <asm/uaccess.h>
24
25static short pw = 80 - 1, ph = 34 - 1;
26static short px, py;
27static unsigned long promcon_uni_pagedir[2];
28
29extern u8 promfont_unicount[];
30extern u16 promfont_unitable[];
31
32#define PROMCON_COLOR 0
33
34#if PROMCON_COLOR
35#define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1)
36#else
37#define inverted(s) (((s) & 0x0800) ? 1 : 0)
38#endif
39
40static __inline__ void
41promcon_puts(char *buf, int cnt)
42{
43 prom_printf("%*.*s", cnt, cnt, buf);
44}
45
46static int
47promcon_start(struct vc_data *conp, char *b)
48{
49 unsigned short *s = (unsigned short *)
50 (conp->vc_origin + py * conp->vc_size_row + (px << 1));
51 u16 cs;
52
53 cs = scr_readw(s);
54 if (px == pw) {
55 unsigned short *t = s - 1;
56 u16 ct = scr_readw(t);
57
58 if (inverted(cs) && inverted(ct))
59 return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
60 ct);
61 else if (inverted(cs))
62 return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
63 ct);
64 else if (inverted(ct))
65 return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
66 ct);
67 else
68 return sprintf(b, "\b%c\b\033[@%c", cs, ct);
69 }
70
71 if (inverted(cs))
72 return sprintf(b, "\033[7m%c\033[m\b", cs);
73 else
74 return sprintf(b, "%c\b", cs);
75}
76
77static int
78promcon_end(struct vc_data *conp, char *b)
79{
80 unsigned short *s = (unsigned short *)
81 (conp->vc_origin + py * conp->vc_size_row + (px << 1));
82 char *p = b;
83 u16 cs;
84
85 b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
86
87 cs = scr_readw(s);
88 if (px == pw) {
89 unsigned short *t = s - 1;
90 u16 ct = scr_readw(t);
91
92 if (inverted(cs) && inverted(ct))
93 b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct);
94 else if (inverted(cs))
95 b += sprintf(b, "\b%c\b\033[@%c", cs, ct);
96 else if (inverted(ct))
97 b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct);
98 else
99 b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
100 return b - p;
101 }
102
103 if (inverted(cs))
104 b += sprintf(b, "%c\b", cs);
105 else
106 b += sprintf(b, "\033[7m%c\033[m\b", cs);
107 return b - p;
108}
109
110const char *promcon_startup(void)
111{
112 const char *display_desc = "PROM";
113 int node;
114 char buf[40];
115
116 node = prom_getchild(prom_root_node);
117 node = prom_searchsiblings(node, "options");
118 if (prom_getproperty(node, "screen-#columns", buf, 40) != -1) {
119 pw = simple_strtoul(buf, NULL, 0);
120 if (pw < 10 || pw > 256)
121 pw = 80;
122 pw--;
123 }
124 if (prom_getproperty(node, "screen-#rows", buf, 40) != -1) {
125 ph = simple_strtoul(buf, NULL, 0);
126 if (ph < 10 || ph > 256)
127 ph = 34;
128 ph--;
129 }
130 promcon_puts("\033[H\033[J", 6);
131 return display_desc;
132}
133
134static void
135promcon_init_unimap(struct vc_data *conp)
136{
137 mm_segment_t old_fs = get_fs();
138 struct unipair *p, *p1;
139 u16 *q;
140 int i, j, k;
141
142 p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
143 if (!p) return;
144
145 q = promfont_unitable;
146 p1 = p;
147 k = 0;
148 for (i = 0; i < 256; i++)
149 for (j = promfont_unicount[i]; j; j--) {
150 p1->unicode = *q++;
151 p1->fontpos = i;
152 p1++;
153 k++;
154 }
155 set_fs(KERNEL_DS);
156 con_clear_unimap(conp, NULL);
157 con_set_unimap(conp, k, p);
158 con_protect_unimap(conp, 1);
159 set_fs(old_fs);
160 kfree(p);
161}
162
163static void
164promcon_init(struct vc_data *conp, int init)
165{
166 unsigned long p;
167
168 conp->vc_can_do_color = PROMCON_COLOR;
169 if (init) {
170 conp->vc_cols = pw + 1;
171 conp->vc_rows = ph + 1;
172 }
173 p = *conp->vc_uni_pagedir_loc;
174 if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
175 !--conp->vc_uni_pagedir_loc[1])
176 con_free_unimap(conp);
177 conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
178 promcon_uni_pagedir[1]++;
179 if (!promcon_uni_pagedir[0] && p) {
180 promcon_init_unimap(conp);
181 }
182 if (!init) {
183 if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
184 vc_resize(conp, pw + 1, ph + 1);
185 }
186}
187
188static void
189promcon_deinit(struct vc_data *conp)
190{
191 /* When closing the last console, reset video origin */
192 if (!--promcon_uni_pagedir[1])
193 con_free_unimap(conp);
194 conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
195 con_set_default_unimap(conp);
196}
197
198static int
199promcon_switch(struct vc_data *conp)
200{
201 return 1;
202}
203
204static unsigned short *
205promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
206{
207 int cnt = pw + 1;
208 int attr = -1;
209 unsigned char *b = *bp;
210
211 while (cnt--) {
212 u16 c = scr_readw(s);
213 if (attr != inverted(c)) {
214 attr = inverted(c);
215 if (attr) {
216 strcpy (b, "\033[7m");
217 b += 4;
218 } else {
219 strcpy (b, "\033[m");
220 b += 3;
221 }
222 }
223 *b++ = c;
224 s++;
225 if (b - buf >= 224) {
226 promcon_puts(buf, b - buf);
227 b = buf;
228 }
229 }
230 *bp = b;
231 return s;
232}
233
234static void
235promcon_putcs(struct vc_data *conp, const unsigned short *s,
236 int count, int y, int x)
237{
238 unsigned char buf[256], *b = buf;
239 unsigned short attr = scr_readw(s);
240 unsigned char save;
241 int i, last = 0;
242
243 if (console_blanked)
244 return;
245
246 if (count <= 0)
247 return;
248
249 b += promcon_start(conp, b);
250
251 if (x + count >= pw + 1) {
252 if (count == 1) {
253 x -= 1;
254 save = scr_readw((unsigned short *)(conp->vc_origin
255 + y * conp->vc_size_row
256 + (x << 1)));
257
258 if (px != x || py != y) {
259 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
260 px = x;
261 py = y;
262 }
263
264 if (inverted(attr))
265 b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
266 else
267 b += sprintf(b, "%c", scr_readw(s++));
268
269 strcpy(b, "\b\033[@");
270 b += 4;
271
272 if (inverted(save))
273 b += sprintf(b, "\033[7m%c\033[m", save);
274 else
275 b += sprintf(b, "%c", save);
276
277 px++;
278
279 b += promcon_end(conp, b);
280 promcon_puts(buf, b - buf);
281 return;
282 } else {
283 last = 1;
284 count = pw - x - 1;
285 }
286 }
287
288 if (inverted(attr)) {
289 strcpy(b, "\033[7m");
290 b += 4;
291 }
292
293 if (px != x || py != y) {
294 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
295 px = x;
296 py = y;
297 }
298
299 for (i = 0; i < count; i++) {
300 if (b - buf >= 224) {
301 promcon_puts(buf, b - buf);
302 b = buf;
303 }
304 *b++ = scr_readw(s++);
305 }
306
307 px += count;
308
309 if (last) {
310 save = scr_readw(s++);
311 b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
312 px++;
313 }
314
315 if (inverted(attr)) {
316 strcpy(b, "\033[m");
317 b += 3;
318 }
319
320 b += promcon_end(conp, b);
321 promcon_puts(buf, b - buf);
322}
323
324static void
325promcon_putc(struct vc_data *conp, int c, int y, int x)
326{
327 unsigned short s;
328
329 if (console_blanked)
330 return;
331
332 scr_writew(c, &s);
333 promcon_putcs(conp, &s, 1, y, x);
334}
335
336static void
337promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
338{
339 unsigned char buf[256], *b = buf;
340 int i, j;
341
342 if (console_blanked)
343 return;
344
345 b += promcon_start(conp, b);
346
347 if (!sx && width == pw + 1) {
348
349 if (!sy && height == ph + 1) {
350 strcpy(b, "\033[H\033[J");
351 b += 6;
352 b += promcon_end(conp, b);
353 promcon_puts(buf, b - buf);
354 return;
355 } else if (sy + height == ph + 1) {
356 b += sprintf(b, "\033[%dH\033[J", sy + 1);
357 b += promcon_end(conp, b);
358 promcon_puts(buf, b - buf);
359 return;
360 }
361
362 b += sprintf(b, "\033[%dH", sy + 1);
363 for (i = 1; i < height; i++) {
364 strcpy(b, "\033[K\n");
365 b += 4;
366 }
367
368 strcpy(b, "\033[K");
369 b += 3;
370
371 b += promcon_end(conp, b);
372 promcon_puts(buf, b - buf);
373 return;
374
375 } else if (sx + width == pw + 1) {
376
377 b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
378 for (i = 1; i < height; i++) {
379 strcpy(b, "\033[K\n");
380 b += 4;
381 }
382
383 strcpy(b, "\033[K");
384 b += 3;
385
386 b += promcon_end(conp, b);
387 promcon_puts(buf, b - buf);
388 return;
389 }
390
391 for (i = sy + 1; i <= sy + height; i++) {
392 b += sprintf(b, "\033[%d;%dH", i, sx + 1);
393 for (j = 0; j < width; j++)
394 *b++ = ' ';
395 if (b - buf + width >= 224) {
396 promcon_puts(buf, b - buf);
397 b = buf;
398 }
399 }
400
401 b += promcon_end(conp, b);
402 promcon_puts(buf, b - buf);
403}
404
405static void
406promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
407 int height, int width)
408{
409 char buf[256], *b = buf;
410
411 if (console_blanked)
412 return;
413
414 b += promcon_start(conp, b);
415 if (sy == dy && height == 1) {
416 if (dx > sx && dx + width == conp->vc_cols)
417 b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
418 sy + 1, sx + 1, dx - sx, py + 1, px + 1);
419 else if (dx < sx && sx + width == conp->vc_cols)
420 b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
421 dy + 1, dx + 1, sx - dx, py + 1, px + 1);
422
423 b += promcon_end(conp, b);
424 promcon_puts(buf, b - buf);
425 return;
426 }
427
428 /*
429 * FIXME: What to do here???
430 * Current console.c should not call it like that ever.
431 */
432 prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
433}
434
435static void
436promcon_cursor(struct vc_data *conp, int mode)
437{
438 char buf[32], *b = buf;
439
440 switch (mode) {
441 case CM_ERASE:
442 break;
443
444 case CM_MOVE:
445 case CM_DRAW:
446 b += promcon_start(conp, b);
447 if (px != conp->vc_x || py != conp->vc_y) {
448 px = conp->vc_x;
449 py = conp->vc_y;
450 b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
451 }
452 promcon_puts(buf, b - buf);
453 break;
454 }
455}
456
457static int
458promcon_blank(struct vc_data *conp, int blank, int mode_switch)
459{
460 if (blank) {
461 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
462 return 0;
463 } else {
464 /* Let console.c redraw */
465 return 1;
466 }
467}
468
469static int
470promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
471{
472 unsigned char buf[256], *p = buf;
473 unsigned short *s;
474 int i;
475
476 if (console_blanked)
477 return 0;
478
479 p += promcon_start(conp, p);
480
481 switch (dir) {
482 case SM_UP:
483 if (b == ph + 1) {
484 p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
485 px = 0;
486 py = t;
487 p += promcon_end(conp, p);
488 promcon_puts(buf, p - buf);
489 break;
490 }
491
492 s = (unsigned short *)(conp->vc_origin
493 + (t + count) * conp->vc_size_row);
494
495 p += sprintf(p, "\033[%dH", t + 1);
496
497 for (i = t; i < b - count; i++)
498 s = promcon_repaint_line(s, buf, &p);
499
500 for (; i < b - 1; i++) {
501 strcpy(p, "\033[K\n");
502 p += 4;
503 if (p - buf >= 224) {
504 promcon_puts(buf, p - buf);
505 p = buf;
506 }
507 }
508
509 strcpy(p, "\033[K");
510 p += 3;
511
512 p += promcon_end(conp, p);
513 promcon_puts(buf, p - buf);
514 break;
515
516 case SM_DOWN:
517 if (b == ph + 1) {
518 p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
519 px = 0;
520 py = t;
521 p += promcon_end(conp, p);
522 promcon_puts(buf, p - buf);
523 break;
524 }
525
526 s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
527
528 p += sprintf(p, "\033[%dH", t + 1);
529
530 for (i = t; i < t + count; i++) {
531 strcpy(p, "\033[K\n");
532 p += 4;
533 if (p - buf >= 224) {
534 promcon_puts(buf, p - buf);
535 p = buf;
536 }
537 }
538
539 for (; i < b; i++)
540 s = promcon_repaint_line(s, buf, &p);
541
542 p += promcon_end(conp, p);
543 promcon_puts(buf, p - buf);
544 break;
545 }
546
547 return 0;
548}
549
550#if !(PROMCON_COLOR)
551static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity,
552 u8 _blink, u8 _underline, u8 _reverse, u8 _italic)
553{
554 return (_reverse) ? 0xf : 0x7;
555}
556#endif
557
558/*
559 * The console 'switch' structure for the VGA based console
560 */
561
562static int promcon_dummy(void)
563{
564 return 0;
565}
566
567#define DUMMY (void *) promcon_dummy
568
569const struct consw prom_con = {
570 .owner = THIS_MODULE,
571 .con_startup = promcon_startup,
572 .con_init = promcon_init,
573 .con_deinit = promcon_deinit,
574 .con_clear = promcon_clear,
575 .con_putc = promcon_putc,
576 .con_putcs = promcon_putcs,
577 .con_cursor = promcon_cursor,
578 .con_scroll = promcon_scroll,
579 .con_bmove = promcon_bmove,
580 .con_switch = promcon_switch,
581 .con_blank = promcon_blank,
582 .con_set_palette = DUMMY,
583 .con_scrolldelta = DUMMY,
584#if !(PROMCON_COLOR)
585 .con_build_attr = promcon_build_attr,
586#endif
587};
588
589void __init prom_con_init(void)
590{
591#ifdef CONFIG_DUMMY_CONSOLE
592 if (conswitchp == &dummy_con)
593 take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
594 else
595#endif
596 if (conswitchp == &prom_con)
597 promcon_init_unimap(vc_cons[fg_console].d);
598}
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index ef7870f5ea08..857b3668b3ba 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -957,9 +957,14 @@ static int __devinit sticore_pci_init(struct pci_dev *pd,
957#ifdef CONFIG_PCI 957#ifdef CONFIG_PCI
958 unsigned long fb_base, rom_base; 958 unsigned long fb_base, rom_base;
959 unsigned int fb_len, rom_len; 959 unsigned int fb_len, rom_len;
960 int err;
960 struct sti_struct *sti; 961 struct sti_struct *sti;
961 962
962 pci_enable_device(pd); 963 err = pci_enable_device(pd);
964 if (err < 0) {
965 dev_err(&pd->dev, "Cannot enable PCI device\n");
966 return err;
967 }
963 968
964 fb_base = pci_resource_start(pd, 0); 969 fb_base = pci_resource_start(pd, 0);
965 fb_len = pci_resource_len(pd, 0); 970 fb_len = pci_resource_len(pd, 0);
@@ -1048,7 +1053,7 @@ static void __devinit sti_init_roms(void)
1048 1053
1049 /* Register drivers for native & PCI cards */ 1054 /* Register drivers for native & PCI cards */
1050 register_parisc_driver(&pa_sti_driver); 1055 register_parisc_driver(&pa_sti_driver);
1051 pci_register_driver(&pci_sti_driver); 1056 WARN_ON(pci_register_driver(&pci_sti_driver));
1052 1057
1053 /* if we didn't find the given default sti, take the first one */ 1058 /* if we didn't find the given default sti, take the first one */
1054 if (!default_sti) 1059 if (!default_sti)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 59d7d5ec17a4..da55ccaf4d55 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -180,7 +180,6 @@ static inline void vga_set_mem_top(struct vc_data *c)
180} 180}
181 181
182#ifdef CONFIG_VGACON_SOFT_SCROLLBACK 182#ifdef CONFIG_VGACON_SOFT_SCROLLBACK
183#include <linux/slab.h>
184/* software scrollback */ 183/* software scrollback */
185static void *vgacon_scrollback; 184static void *vgacon_scrollback;
186static int vgacon_scrollback_tail; 185static int vgacon_scrollback_tail;
@@ -590,12 +589,14 @@ static void vgacon_init(struct vc_data *c, int init)
590 589
591static void vgacon_deinit(struct vc_data *c) 590static void vgacon_deinit(struct vc_data *c)
592{ 591{
593 /* When closing the last console, reset video origin */ 592 /* When closing the active console, reset video origin */
594 if (!--vgacon_uni_pagedir[1]) { 593 if (CON_IS_VISIBLE(c)) {
595 c->vc_visible_origin = vga_vram_base; 594 c->vc_visible_origin = vga_vram_base;
596 vga_set_mem_top(c); 595 vga_set_mem_top(c);
597 con_free_unimap(c);
598 } 596 }
597
598 if (!--vgacon_uni_pagedir[1])
599 con_free_unimap(c);
599 c->vc_uni_pagedir_loc = &c->vc_uni_pagedir; 600 c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
600 con_set_default_unimap(c); 601 con_set_default_unimap(c);
601} 602}
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
new file mode 100644
index 000000000000..035d56835b75
--- /dev/null
+++ b/drivers/video/da8xx-fb.c
@@ -0,0 +1,889 @@
1/*
2 * Copyright (C) 2008-2009 MontaVista Software Inc.
3 * Copyright (C) 2008-2009 Texas Instruments Inc
4 *
5 * Based on the LCD driver for TI Avalanche processors written by
6 * Ajay Singh and Shalom Hai.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option)any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/fb.h>
25#include <linux/dma-mapping.h>
26#include <linux/device.h>
27#include <linux/platform_device.h>
28#include <linux/uaccess.h>
29#include <linux/interrupt.h>
30#include <linux/clk.h>
31#include <video/da8xx-fb.h>
32
33#define DRIVER_NAME "da8xx_lcdc"
34
35/* LCD Status Register */
36#define LCD_END_OF_FRAME0 BIT(8)
37#define LCD_FIFO_UNDERFLOW BIT(5)
38#define LCD_SYNC_LOST BIT(2)
39
40/* LCD DMA Control Register */
41#define LCD_DMA_BURST_SIZE(x) ((x) << 4)
42#define LCD_DMA_BURST_1 0x0
43#define LCD_DMA_BURST_2 0x1
44#define LCD_DMA_BURST_4 0x2
45#define LCD_DMA_BURST_8 0x3
46#define LCD_DMA_BURST_16 0x4
47#define LCD_END_OF_FRAME_INT_ENA BIT(2)
48#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0)
49
50/* LCD Control Register */
51#define LCD_CLK_DIVISOR(x) ((x) << 8)
52#define LCD_RASTER_MODE 0x01
53
54/* LCD Raster Control Register */
55#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20)
56#define PALETTE_AND_DATA 0x00
57#define PALETTE_ONLY 0x01
58
59#define LCD_MONO_8BIT_MODE BIT(9)
60#define LCD_RASTER_ORDER BIT(8)
61#define LCD_TFT_MODE BIT(7)
62#define LCD_UNDERFLOW_INT_ENA BIT(6)
63#define LCD_MONOCHROME_MODE BIT(1)
64#define LCD_RASTER_ENABLE BIT(0)
65#define LCD_TFT_ALT_ENABLE BIT(23)
66#define LCD_STN_565_ENABLE BIT(24)
67
68/* LCD Raster Timing 2 Register */
69#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
70#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8)
71#define LCD_SYNC_CTRL BIT(25)
72#define LCD_SYNC_EDGE BIT(24)
73#define LCD_INVERT_PIXEL_CLOCK BIT(22)
74#define LCD_INVERT_LINE_CLOCK BIT(21)
75#define LCD_INVERT_FRAME_CLOCK BIT(20)
76
77/* LCD Block */
78#define LCD_CTRL_REG 0x4
79#define LCD_STAT_REG 0x8
80#define LCD_RASTER_CTRL_REG 0x28
81#define LCD_RASTER_TIMING_0_REG 0x2C
82#define LCD_RASTER_TIMING_1_REG 0x30
83#define LCD_RASTER_TIMING_2_REG 0x34
84#define LCD_DMA_CTRL_REG 0x40
85#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44
86#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48
87
88#define WSI_TIMEOUT 50
89#define PALETTE_SIZE 256
90#define LEFT_MARGIN 64
91#define RIGHT_MARGIN 64
92#define UPPER_MARGIN 32
93#define LOWER_MARGIN 32
94
95static resource_size_t da8xx_fb_reg_base;
96static struct resource *lcdc_regs;
97
98static inline unsigned int lcdc_read(unsigned int addr)
99{
100 return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
101}
102
103static inline void lcdc_write(unsigned int val, unsigned int addr)
104{
105 __raw_writel(val, da8xx_fb_reg_base + (addr));
106}
107
108struct da8xx_fb_par {
109 resource_size_t p_palette_base;
110 unsigned char *v_palette_base;
111 struct clk *lcdc_clk;
112 int irq;
113 unsigned short pseudo_palette[16];
114 unsigned int databuf_sz;
115 unsigned int palette_sz;
116};
117
118/* Variable Screen Information */
119static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
120 .xoffset = 0,
121 .yoffset = 0,
122 .transp = {0, 0, 0},
123 .nonstd = 0,
124 .activate = 0,
125 .height = -1,
126 .width = -1,
127 .pixclock = 46666, /* 46us - AUO display */
128 .accel_flags = 0,
129 .left_margin = LEFT_MARGIN,
130 .right_margin = RIGHT_MARGIN,
131 .upper_margin = UPPER_MARGIN,
132 .lower_margin = LOWER_MARGIN,
133 .sync = 0,
134 .vmode = FB_VMODE_NONINTERLACED
135};
136
137static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
138 .id = "DA8xx FB Drv",
139 .type = FB_TYPE_PACKED_PIXELS,
140 .type_aux = 0,
141 .visual = FB_VISUAL_PSEUDOCOLOR,
142 .xpanstep = 1,
143 .ypanstep = 1,
144 .ywrapstep = 1,
145 .accel = FB_ACCEL_NONE
146};
147
148struct da8xx_panel {
149 const char name[25]; /* Full name <vendor>_<model> */
150 unsigned short width;
151 unsigned short height;
152 int hfp; /* Horizontal front porch */
153 int hbp; /* Horizontal back porch */
154 int hsw; /* Horizontal Sync Pulse Width */
155 int vfp; /* Vertical front porch */
156 int vbp; /* Vertical back porch */
157 int vsw; /* Vertical Sync Pulse Width */
158 int pxl_clk; /* Pixel clock */
159 unsigned char invert_pxl_clk; /* Invert Pixel clock */
160};
161
162static struct da8xx_panel known_lcd_panels[] = {
163 /* Sharp LCD035Q3DG01 */
164 [0] = {
165 .name = "Sharp_LCD035Q3DG01",
166 .width = 320,
167 .height = 240,
168 .hfp = 8,
169 .hbp = 6,
170 .hsw = 0,
171 .vfp = 2,
172 .vbp = 2,
173 .vsw = 0,
174 .pxl_clk = 0x10,
175 .invert_pxl_clk = 1,
176 },
177 /* Sharp LK043T1DG01 */
178 [1] = {
179 .name = "Sharp_LK043T1DG01",
180 .width = 480,
181 .height = 272,
182 .hfp = 2,
183 .hbp = 2,
184 .hsw = 41,
185 .vfp = 2,
186 .vbp = 2,
187 .vsw = 10,
188 .pxl_clk = 0x12,
189 .invert_pxl_clk = 0,
190 },
191};
192
193/* Disable the Raster Engine of the LCD Controller */
194static void lcd_disable_raster(struct da8xx_fb_par *par)
195{
196 u32 reg;
197
198 reg = lcdc_read(LCD_RASTER_CTRL_REG);
199 if (reg & LCD_RASTER_ENABLE)
200 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
201}
202
203static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
204{
205 u32 tmp = par->p_palette_base + par->databuf_sz - 4;
206 u32 reg;
207
208 /* Update the databuf in the hw. */
209 lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
210 lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
211
212 /* Start the DMA. */
213 reg = lcdc_read(LCD_RASTER_CTRL_REG);
214 reg &= ~(3 << 20);
215 if (load_mode == LOAD_DATA)
216 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA);
217 else if (load_mode == LOAD_PALETTE)
218 reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
219
220 lcdc_write(reg, LCD_RASTER_CTRL_REG);
221}
222
223/* Configure the Burst Size of DMA */
224static int lcd_cfg_dma(int burst_size)
225{
226 u32 reg;
227
228 reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001;
229 switch (burst_size) {
230 case 1:
231 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1);
232 break;
233 case 2:
234 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2);
235 break;
236 case 4:
237 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4);
238 break;
239 case 8:
240 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
241 break;
242 case 16:
243 reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
244 break;
245 default:
246 return -EINVAL;
247 }
248 lcdc_write(reg, LCD_DMA_CTRL_REG);
249
250 return 0;
251}
252
253static void lcd_cfg_ac_bias(int period, int transitions_per_int)
254{
255 u32 reg;
256
257 /* Set the AC Bias Period and Number of Transisitons per Interrupt */
258 reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000;
259 reg |= LCD_AC_BIAS_FREQUENCY(period) |
260 LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int);
261 lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
262}
263
264static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
265 int front_porch)
266{
267 u32 reg;
268
269 reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
270 reg |= ((back_porch & 0xff) << 24)
271 | ((front_porch & 0xff) << 16)
272 | ((pulse_width & 0x3f) << 10);
273 lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
274}
275
276static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
277 int front_porch)
278{
279 u32 reg;
280
281 reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff;
282 reg |= ((back_porch & 0xff) << 24)
283 | ((front_porch & 0xff) << 16)
284 | ((pulse_width & 0x3f) << 10);
285 lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
286}
287
288static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
289{
290 u32 reg;
291
292 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
293 LCD_MONO_8BIT_MODE |
294 LCD_MONOCHROME_MODE);
295
296 switch (cfg->p_disp_panel->panel_shade) {
297 case MONOCHROME:
298 reg |= LCD_MONOCHROME_MODE;
299 if (cfg->mono_8bit_mode)
300 reg |= LCD_MONO_8BIT_MODE;
301 break;
302 case COLOR_ACTIVE:
303 reg |= LCD_TFT_MODE;
304 if (cfg->tft_alt_mode)
305 reg |= LCD_TFT_ALT_ENABLE;
306 break;
307
308 case COLOR_PASSIVE:
309 if (cfg->stn_565_mode)
310 reg |= LCD_STN_565_ENABLE;
311 break;
312
313 default:
314 return -EINVAL;
315 }
316
317 /* enable additional interrupts here */
318 reg |= LCD_UNDERFLOW_INT_ENA;
319
320 lcdc_write(reg, LCD_RASTER_CTRL_REG);
321
322 reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
323
324 if (cfg->sync_ctrl)
325 reg |= LCD_SYNC_CTRL;
326 else
327 reg &= ~LCD_SYNC_CTRL;
328
329 if (cfg->sync_edge)
330 reg |= LCD_SYNC_EDGE;
331 else
332 reg &= ~LCD_SYNC_EDGE;
333
334 if (cfg->invert_line_clock)
335 reg |= LCD_INVERT_LINE_CLOCK;
336 else
337 reg &= ~LCD_INVERT_LINE_CLOCK;
338
339 if (cfg->invert_frm_clock)
340 reg |= LCD_INVERT_FRAME_CLOCK;
341 else
342 reg &= ~LCD_INVERT_FRAME_CLOCK;
343
344 lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
345
346 return 0;
347}
348
349static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
350 u32 bpp, u32 raster_order)
351{
352 u32 bpl, reg;
353
354 /* Disable Dual Frame Buffer. */
355 reg = lcdc_read(LCD_DMA_CTRL_REG);
356 lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE,
357 LCD_DMA_CTRL_REG);
358 /* Set the Panel Width */
359 /* Pixels per line = (PPL + 1)*16 */
360 /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/
361 width &= 0x3f0;
362 reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
363 reg &= 0xfffffc00;
364 reg |= ((width >> 4) - 1) << 4;
365 lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
366
367 /* Set the Panel Height */
368 reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
369 reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
370 lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
371
372 /* Set the Raster Order of the Frame Buffer */
373 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
374 if (raster_order)
375 reg |= LCD_RASTER_ORDER;
376 lcdc_write(reg, LCD_RASTER_CTRL_REG);
377
378 switch (bpp) {
379 case 1:
380 case 2:
381 case 4:
382 case 16:
383 par->palette_sz = 16 * 2;
384 break;
385
386 case 8:
387 par->palette_sz = 256 * 2;
388 break;
389
390 default:
391 return -EINVAL;
392 }
393
394 bpl = width * bpp / 8;
395 par->databuf_sz = height * bpl + par->palette_sz;
396
397 return 0;
398}
399
400static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
401 unsigned blue, unsigned transp,
402 struct fb_info *info)
403{
404 struct da8xx_fb_par *par = info->par;
405 unsigned short *palette = (unsigned short *)par->v_palette_base;
406 u_short pal;
407
408 if (regno > 255)
409 return 1;
410
411 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
412 return 1;
413
414 if (info->var.bits_per_pixel == 8) {
415 red >>= 4;
416 green >>= 8;
417 blue >>= 12;
418
419 pal = (red & 0x0f00);
420 pal |= (green & 0x00f0);
421 pal |= (blue & 0x000f);
422
423 palette[regno] = pal;
424
425 } else if ((info->var.bits_per_pixel == 16) && regno < 16) {
426 red >>= (16 - info->var.red.length);
427 red <<= info->var.red.offset;
428
429 green >>= (16 - info->var.green.length);
430 green <<= info->var.green.offset;
431
432 blue >>= (16 - info->var.blue.length);
433 blue <<= info->var.blue.offset;
434
435 par->pseudo_palette[regno] = red | green | blue;
436
437 palette[0] = 0x4000;
438 }
439
440 return 0;
441}
442
443static void lcd_reset(struct da8xx_fb_par *par)
444{
445 /* Disable the Raster if previously Enabled */
446 if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
447 lcd_disable_raster(par);
448
449 /* DMA has to be disabled */
450 lcdc_write(0, LCD_DMA_CTRL_REG);
451 lcdc_write(0, LCD_RASTER_CTRL_REG);
452}
453
454static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
455 struct da8xx_panel *panel)
456{
457 u32 bpp;
458 int ret = 0;
459
460 lcd_reset(par);
461
462 /* Configure the LCD clock divisor. */
463 lcdc_write(LCD_CLK_DIVISOR(panel->pxl_clk) |
464 (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
465
466 if (panel->invert_pxl_clk)
467 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
468 LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
469 else
470 lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
471 ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
472
473 /* Configure the DMA burst size. */
474 ret = lcd_cfg_dma(cfg->dma_burst_sz);
475 if (ret < 0)
476 return ret;
477
478 /* Configure the AC bias properties. */
479 lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
480
481 /* Configure the vertical and horizontal sync properties. */
482 lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
483 lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
484
485 /* Configure for disply */
486 ret = lcd_cfg_display(cfg);
487 if (ret < 0)
488 return ret;
489
490 if (QVGA != cfg->p_disp_panel->panel_type)
491 return -EINVAL;
492
493 if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
494 cfg->bpp >= cfg->p_disp_panel->min_bpp)
495 bpp = cfg->bpp;
496 else
497 bpp = cfg->p_disp_panel->max_bpp;
498 if (bpp == 12)
499 bpp = 16;
500 ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
501 (unsigned int)panel->height, bpp,
502 cfg->raster_order);
503 if (ret < 0)
504 return ret;
505
506 /* Configure FDD */
507 lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) |
508 (cfg->fdd << 12), LCD_RASTER_CTRL_REG);
509
510 return 0;
511}
512
513static irqreturn_t lcdc_irq_handler(int irq, void *arg)
514{
515 u32 stat = lcdc_read(LCD_STAT_REG);
516 u32 reg;
517
518 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
519 reg = lcdc_read(LCD_RASTER_CTRL_REG);
520 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
521 lcdc_write(stat, LCD_STAT_REG);
522 lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
523 } else
524 lcdc_write(stat, LCD_STAT_REG);
525
526 return IRQ_HANDLED;
527}
528
529static int fb_check_var(struct fb_var_screeninfo *var,
530 struct fb_info *info)
531{
532 int err = 0;
533
534 switch (var->bits_per_pixel) {
535 case 1:
536 case 8:
537 var->red.offset = 0;
538 var->red.length = 8;
539 var->green.offset = 0;
540 var->green.length = 8;
541 var->blue.offset = 0;
542 var->blue.length = 8;
543 var->transp.offset = 0;
544 var->transp.length = 0;
545 break;
546 case 4:
547 var->red.offset = 0;
548 var->red.length = 4;
549 var->green.offset = 0;
550 var->green.length = 4;
551 var->blue.offset = 0;
552 var->blue.length = 4;
553 var->transp.offset = 0;
554 var->transp.length = 0;
555 break;
556 case 16: /* RGB 565 */
557 var->red.offset = 0;
558 var->red.length = 5;
559 var->green.offset = 5;
560 var->green.length = 6;
561 var->blue.offset = 11;
562 var->blue.length = 5;
563 var->transp.offset = 0;
564 var->transp.length = 0;
565 break;
566 default:
567 err = -EINVAL;
568 }
569
570 var->red.msb_right = 0;
571 var->green.msb_right = 0;
572 var->blue.msb_right = 0;
573 var->transp.msb_right = 0;
574 return err;
575}
576
577static int __devexit fb_remove(struct platform_device *dev)
578{
579 struct fb_info *info = dev_get_drvdata(&dev->dev);
580
581 if (info) {
582 struct da8xx_fb_par *par = info->par;
583
584 if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
585 lcd_disable_raster(par);
586 lcdc_write(0, LCD_RASTER_CTRL_REG);
587
588 /* disable DMA */
589 lcdc_write(0, LCD_DMA_CTRL_REG);
590
591 unregister_framebuffer(info);
592 fb_dealloc_cmap(&info->cmap);
593 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE,
594 info->screen_base,
595 info->fix.smem_start);
596 free_irq(par->irq, par);
597 clk_disable(par->lcdc_clk);
598 clk_put(par->lcdc_clk);
599 framebuffer_release(info);
600 iounmap((void __iomem *)da8xx_fb_reg_base);
601 release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
602
603 }
604 return 0;
605}
606
607static int fb_ioctl(struct fb_info *info, unsigned int cmd,
608 unsigned long arg)
609{
610 struct lcd_sync_arg sync_arg;
611
612 switch (cmd) {
613 case FBIOGET_CONTRAST:
614 case FBIOPUT_CONTRAST:
615 case FBIGET_BRIGHTNESS:
616 case FBIPUT_BRIGHTNESS:
617 case FBIGET_COLOR:
618 case FBIPUT_COLOR:
619 return -ENOTTY;
620 case FBIPUT_HSYNC:
621 if (copy_from_user(&sync_arg, (char *)arg,
622 sizeof(struct lcd_sync_arg)))
623 return -EFAULT;
624 lcd_cfg_horizontal_sync(sync_arg.back_porch,
625 sync_arg.pulse_width,
626 sync_arg.front_porch);
627 break;
628 case FBIPUT_VSYNC:
629 if (copy_from_user(&sync_arg, (char *)arg,
630 sizeof(struct lcd_sync_arg)))
631 return -EFAULT;
632 lcd_cfg_vertical_sync(sync_arg.back_porch,
633 sync_arg.pulse_width,
634 sync_arg.front_porch);
635 break;
636 default:
637 return -EINVAL;
638 }
639 return 0;
640}
641
642static struct fb_ops da8xx_fb_ops = {
643 .owner = THIS_MODULE,
644 .fb_check_var = fb_check_var,
645 .fb_setcolreg = fb_setcolreg,
646 .fb_ioctl = fb_ioctl,
647 .fb_fillrect = cfb_fillrect,
648 .fb_copyarea = cfb_copyarea,
649 .fb_imageblit = cfb_imageblit,
650};
651
652static int __init fb_probe(struct platform_device *device)
653{
654 struct da8xx_lcdc_platform_data *fb_pdata =
655 device->dev.platform_data;
656 struct lcd_ctrl_config *lcd_cfg;
657 struct da8xx_panel *lcdc_info;
658 struct fb_info *da8xx_fb_info;
659 struct clk *fb_clk = NULL;
660 struct da8xx_fb_par *par;
661 resource_size_t len;
662 int ret, i;
663
664 if (fb_pdata == NULL) {
665 dev_err(&device->dev, "Can not get platform data\n");
666 return -ENOENT;
667 }
668
669 lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
670 if (!lcdc_regs) {
671 dev_err(&device->dev,
672 "Can not get memory resource for LCD controller\n");
673 return -ENOENT;
674 }
675
676 len = resource_size(lcdc_regs);
677
678 lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);
679 if (!lcdc_regs)
680 return -EBUSY;
681
682 da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len);
683 if (!da8xx_fb_reg_base) {
684 ret = -EBUSY;
685 goto err_request_mem;
686 }
687
688 fb_clk = clk_get(&device->dev, NULL);
689 if (IS_ERR(fb_clk)) {
690 dev_err(&device->dev, "Can not get device clock\n");
691 ret = -ENODEV;
692 goto err_ioremap;
693 }
694 ret = clk_enable(fb_clk);
695 if (ret)
696 goto err_clk_put;
697
698 for (i = 0, lcdc_info = known_lcd_panels;
699 i < ARRAY_SIZE(known_lcd_panels);
700 i++, lcdc_info++) {
701 if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
702 break;
703 }
704
705 if (i == ARRAY_SIZE(known_lcd_panels)) {
706 dev_err(&device->dev, "GLCD: No valid panel found\n");
707 ret = -ENODEV;
708 goto err_clk_disable;
709 } else
710 dev_info(&device->dev, "GLCD: Found %s panel\n",
711 fb_pdata->type);
712
713 lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
714
715 da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
716 &device->dev);
717 if (!da8xx_fb_info) {
718 dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
719 ret = -ENOMEM;
720 goto err_clk_disable;
721 }
722
723 par = da8xx_fb_info->par;
724
725 if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
726 dev_err(&device->dev, "lcd_init failed\n");
727 ret = -EFAULT;
728 goto err_release_fb;
729 }
730
731 /* allocate frame buffer */
732 da8xx_fb_info->screen_base = dma_alloc_coherent(NULL,
733 par->databuf_sz + PAGE_SIZE,
734 (resource_size_t *)
735 &da8xx_fb_info->fix.smem_start,
736 GFP_KERNEL | GFP_DMA);
737
738 if (!da8xx_fb_info->screen_base) {
739 dev_err(&device->dev,
740 "GLCD: kmalloc for frame buffer failed\n");
741 ret = -EINVAL;
742 goto err_release_fb;
743 }
744
745 /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */
746 par->v_palette_base = da8xx_fb_info->screen_base +
747 (PAGE_SIZE - par->palette_sz);
748 par->p_palette_base = da8xx_fb_info->fix.smem_start +
749 (PAGE_SIZE - par->palette_sz);
750
751 /* the rest of the frame buffer is pixel data */
752 da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz;
753 da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz;
754 da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
755
756 par->lcdc_clk = fb_clk;
757
758 par->irq = platform_get_irq(device, 0);
759 if (par->irq < 0) {
760 ret = -ENOENT;
761 goto err_release_fb_mem;
762 }
763
764 ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
765 if (ret)
766 goto err_release_fb_mem;
767
768 /* Initialize par */
769 da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
770
771 da8xx_fb_var.xres = lcdc_info->width;
772 da8xx_fb_var.xres_virtual = lcdc_info->width;
773
774 da8xx_fb_var.yres = lcdc_info->height;
775 da8xx_fb_var.yres_virtual = lcdc_info->height;
776
777 da8xx_fb_var.grayscale =
778 lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
779 da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
780
781 da8xx_fb_var.hsync_len = lcdc_info->hsw;
782 da8xx_fb_var.vsync_len = lcdc_info->vsw;
783
784 /* Initialize fbinfo */
785 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
786 da8xx_fb_info->fix = da8xx_fb_fix;
787 da8xx_fb_info->var = da8xx_fb_var;
788 da8xx_fb_info->fbops = &da8xx_fb_ops;
789 da8xx_fb_info->pseudo_palette = par->pseudo_palette;
790
791 ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);
792 if (ret)
793 goto err_free_irq;
794
795 /* First palette_sz byte of the frame buffer is the palette */
796 da8xx_fb_info->cmap.len = par->palette_sz;
797
798 /* Flush the buffer to the screen. */
799 lcd_blit(LOAD_DATA, par);
800
801 /* initialize var_screeninfo */
802 da8xx_fb_var.activate = FB_ACTIVATE_FORCE;
803 fb_set_var(da8xx_fb_info, &da8xx_fb_var);
804
805 dev_set_drvdata(&device->dev, da8xx_fb_info);
806 /* Register the Frame Buffer */
807 if (register_framebuffer(da8xx_fb_info) < 0) {
808 dev_err(&device->dev,
809 "GLCD: Frame Buffer Registration Failed!\n");
810 ret = -EINVAL;
811 goto err_dealloc_cmap;
812 }
813
814 /* enable raster engine */
815 lcdc_write(lcdc_read(LCD_RASTER_CTRL_REG) |
816 LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
817
818 return 0;
819
820err_dealloc_cmap:
821 fb_dealloc_cmap(&da8xx_fb_info->cmap);
822
823err_free_irq:
824 free_irq(par->irq, par);
825
826err_release_fb_mem:
827 dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE,
828 da8xx_fb_info->screen_base,
829 da8xx_fb_info->fix.smem_start);
830
831err_release_fb:
832 framebuffer_release(da8xx_fb_info);
833
834err_clk_disable:
835 clk_disable(fb_clk);
836
837err_clk_put:
838 clk_put(fb_clk);
839
840err_ioremap:
841 iounmap((void __iomem *)da8xx_fb_reg_base);
842
843err_request_mem:
844 release_mem_region(lcdc_regs->start, len);
845
846 return ret;
847}
848
849#ifdef CONFIG_PM
850static int fb_suspend(struct platform_device *dev, pm_message_t state)
851{
852 return -EBUSY;
853}
854static int fb_resume(struct platform_device *dev)
855{
856 return -EBUSY;
857}
858#else
859#define fb_suspend NULL
860#define fb_resume NULL
861#endif
862
863static struct platform_driver da8xx_fb_driver = {
864 .probe = fb_probe,
865 .remove = fb_remove,
866 .suspend = fb_suspend,
867 .resume = fb_resume,
868 .driver = {
869 .name = DRIVER_NAME,
870 .owner = THIS_MODULE,
871 },
872};
873
874static int __init da8xx_fb_init(void)
875{
876 return platform_driver_register(&da8xx_fb_driver);
877}
878
879static void __exit da8xx_fb_cleanup(void)
880{
881 platform_driver_unregister(&da8xx_fb_driver);
882}
883
884module_init(da8xx_fb_init);
885module_exit(da8xx_fb_cleanup);
886
887MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx");
888MODULE_AUTHOR("Texas Instruments");
889MODULE_LICENSE("GPL");
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
new file mode 100644
index 000000000000..bd9d46f95291
--- /dev/null
+++ b/drivers/video/ep93xx-fb.c
@@ -0,0 +1,646 @@
1/*
2 * linux/drivers/video/ep93xx-fb.c
3 *
4 * Framebuffer support for the EP93xx series.
5 *
6 * Copyright (C) 2007 Bluewater Systems Ltd
7 * Author: Ryan Mallon <ryan@bluewatersys.com>
8 *
9 * Copyright (c) 2009 H Hartley Sweeten <hsweeten@visionengravers.com>
10 *
11 * Based on the Cirrus Logic ep93xxfb driver, and various other ep93xxfb
12 * drivers.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 *
18 */
19
20#include <linux/platform_device.h>
21#include <linux/dma-mapping.h>
22#include <linux/clk.h>
23#include <linux/fb.h>
24
25#include <mach/fb.h>
26
27/* Vertical Frame Timing Registers */
28#define EP93XXFB_VLINES_TOTAL 0x0000 /* SW locked */
29#define EP93XXFB_VSYNC 0x0004 /* SW locked */
30#define EP93XXFB_VACTIVE 0x0008 /* SW locked */
31#define EP93XXFB_VBLANK 0x0228 /* SW locked */
32#define EP93XXFB_VCLK 0x000c /* SW locked */
33
34/* Horizontal Frame Timing Registers */
35#define EP93XXFB_HCLKS_TOTAL 0x0010 /* SW locked */
36#define EP93XXFB_HSYNC 0x0014 /* SW locked */
37#define EP93XXFB_HACTIVE 0x0018 /* SW locked */
38#define EP93XXFB_HBLANK 0x022c /* SW locked */
39#define EP93XXFB_HCLK 0x001c /* SW locked */
40
41/* Frame Buffer Memory Configuration Registers */
42#define EP93XXFB_SCREEN_PAGE 0x0028
43#define EP93XXFB_SCREEN_HPAGE 0x002c
44#define EP93XXFB_SCREEN_LINES 0x0030
45#define EP93XXFB_LINE_LENGTH 0x0034
46#define EP93XXFB_VLINE_STEP 0x0038
47#define EP93XXFB_LINE_CARRY 0x003c /* SW locked */
48#define EP93XXFB_EOL_OFFSET 0x0230
49
50/* Other Video Registers */
51#define EP93XXFB_BRIGHTNESS 0x0020
52#define EP93XXFB_ATTRIBS 0x0024 /* SW locked */
53#define EP93XXFB_SWLOCK 0x007c /* SW locked */
54#define EP93XXFB_AC_RATE 0x0214
55#define EP93XXFB_FIFO_LEVEL 0x0234
56#define EP93XXFB_PIXELMODE 0x0054
57#define EP93XXFB_PIXELMODE_32BPP (0x7 << 0)
58#define EP93XXFB_PIXELMODE_24BPP (0x6 << 0)
59#define EP93XXFB_PIXELMODE_16BPP (0x4 << 0)
60#define EP93XXFB_PIXELMODE_8BPP (0x2 << 0)
61#define EP93XXFB_PIXELMODE_SHIFT_1P_24B (0x0 << 3)
62#define EP93XXFB_PIXELMODE_SHIFT_1P_18B (0x1 << 3)
63#define EP93XXFB_PIXELMODE_COLOR_LUT (0x0 << 10)
64#define EP93XXFB_PIXELMODE_COLOR_888 (0x4 << 10)
65#define EP93XXFB_PIXELMODE_COLOR_555 (0x5 << 10)
66#define EP93XXFB_PARL_IF_OUT 0x0058
67#define EP93XXFB_PARL_IF_IN 0x005c
68
69/* Blink Control Registers */
70#define EP93XXFB_BLINK_RATE 0x0040
71#define EP93XXFB_BLINK_MASK 0x0044
72#define EP93XXFB_BLINK_PATTRN 0x0048
73#define EP93XXFB_PATTRN_MASK 0x004c
74#define EP93XXFB_BKGRND_OFFSET 0x0050
75
76/* Hardware Cursor Registers */
77#define EP93XXFB_CURSOR_ADR_START 0x0060
78#define EP93XXFB_CURSOR_ADR_RESET 0x0064
79#define EP93XXFB_CURSOR_SIZE 0x0068
80#define EP93XXFB_CURSOR_COLOR1 0x006c
81#define EP93XXFB_CURSOR_COLOR2 0x0070
82#define EP93XXFB_CURSOR_BLINK_COLOR1 0x021c
83#define EP93XXFB_CURSOR_BLINK_COLOR2 0x0220
84#define EP93XXFB_CURSOR_XY_LOC 0x0074
85#define EP93XXFB_CURSOR_DSCAN_HY_LOC 0x0078
86#define EP93XXFB_CURSOR_BLINK_RATE_CTRL 0x0224
87
88/* LUT Registers */
89#define EP93XXFB_GRY_SCL_LUTR 0x0080
90#define EP93XXFB_GRY_SCL_LUTG 0x0280
91#define EP93XXFB_GRY_SCL_LUTB 0x0300
92#define EP93XXFB_LUT_SW_CONTROL 0x0218
93#define EP93XXFB_LUT_SW_CONTROL_SWTCH (1 << 0)
94#define EP93XXFB_LUT_SW_CONTROL_SSTAT (1 << 1)
95#define EP93XXFB_COLOR_LUT 0x0400
96
97/* Video Signature Registers */
98#define EP93XXFB_VID_SIG_RSLT_VAL 0x0200
99#define EP93XXFB_VID_SIG_CTRL 0x0204
100#define EP93XXFB_VSIG 0x0208
101#define EP93XXFB_HSIG 0x020c
102#define EP93XXFB_SIG_CLR_STR 0x0210
103
104/* Minimum / Maximum resolutions supported */
105#define EP93XXFB_MIN_XRES 64
106#define EP93XXFB_MIN_YRES 64
107#define EP93XXFB_MAX_XRES 1024
108#define EP93XXFB_MAX_YRES 768
109
110struct ep93xx_fbi {
111 struct ep93xxfb_mach_info *mach_info;
112 struct clk *clk;
113 struct resource *res;
114 void __iomem *mmio_base;
115 unsigned int pseudo_palette[256];
116};
117
118static int check_screenpage_bug = 1;
119module_param(check_screenpage_bug, int, 0644);
120MODULE_PARM_DESC(check_screenpage_bug,
121 "Check for bit 27 screen page bug. Default = 1");
122
123static inline unsigned int ep93xxfb_readl(struct ep93xx_fbi *fbi,
124 unsigned int off)
125{
126 return __raw_readl(fbi->mmio_base + off);
127}
128
129static inline void ep93xxfb_writel(struct ep93xx_fbi *fbi,
130 unsigned int val, unsigned int off)
131{
132 __raw_writel(val, fbi->mmio_base + off);
133}
134
135/*
136 * Write to one of the locked raster registers.
137 */
138static inline void ep93xxfb_out_locked(struct ep93xx_fbi *fbi,
139 unsigned int val, unsigned int reg)
140{
141 /*
142 * We don't need a lock or delay here since the raster register
143 * block will remain unlocked until the next access.
144 */
145 ep93xxfb_writel(fbi, 0xaa, EP93XXFB_SWLOCK);
146 ep93xxfb_writel(fbi, val, reg);
147}
148
149static void ep93xxfb_set_video_attribs(struct fb_info *info)
150{
151 struct ep93xx_fbi *fbi = info->par;
152 unsigned int attribs;
153
154 attribs = EP93XXFB_ENABLE;
155 attribs |= fbi->mach_info->flags;
156 ep93xxfb_out_locked(fbi, attribs, EP93XXFB_ATTRIBS);
157}
158
159static int ep93xxfb_set_pixelmode(struct fb_info *info)
160{
161 struct ep93xx_fbi *fbi = info->par;
162 unsigned int val;
163
164 info->var.transp.offset = 0;
165 info->var.transp.length = 0;
166
167 switch (info->var.bits_per_pixel) {
168 case 8:
169 val = EP93XXFB_PIXELMODE_8BPP | EP93XXFB_PIXELMODE_COLOR_LUT |
170 EP93XXFB_PIXELMODE_SHIFT_1P_18B;
171
172 info->var.red.offset = 0;
173 info->var.red.length = 8;
174 info->var.green.offset = 0;
175 info->var.green.length = 8;
176 info->var.blue.offset = 0;
177 info->var.blue.length = 8;
178 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
179 break;
180
181 case 16:
182 val = EP93XXFB_PIXELMODE_16BPP | EP93XXFB_PIXELMODE_COLOR_555 |
183 EP93XXFB_PIXELMODE_SHIFT_1P_18B;
184
185 info->var.red.offset = 11;
186 info->var.red.length = 5;
187 info->var.green.offset = 5;
188 info->var.green.length = 6;
189 info->var.blue.offset = 0;
190 info->var.blue.length = 5;
191 info->fix.visual = FB_VISUAL_TRUECOLOR;
192 break;
193
194 case 24:
195 val = EP93XXFB_PIXELMODE_24BPP | EP93XXFB_PIXELMODE_COLOR_888 |
196 EP93XXFB_PIXELMODE_SHIFT_1P_24B;
197
198 info->var.red.offset = 16;
199 info->var.red.length = 8;
200 info->var.green.offset = 8;
201 info->var.green.length = 8;
202 info->var.blue.offset = 0;
203 info->var.blue.length = 8;
204 info->fix.visual = FB_VISUAL_TRUECOLOR;
205 break;
206
207 case 32:
208 val = EP93XXFB_PIXELMODE_32BPP | EP93XXFB_PIXELMODE_COLOR_888 |
209 EP93XXFB_PIXELMODE_SHIFT_1P_24B;
210
211 info->var.red.offset = 16;
212 info->var.red.length = 8;
213 info->var.green.offset = 8;
214 info->var.green.length = 8;
215 info->var.blue.offset = 0;
216 info->var.blue.length = 8;
217 info->fix.visual = FB_VISUAL_TRUECOLOR;
218 break;
219
220 default:
221 return -EINVAL;
222 }
223
224 ep93xxfb_writel(fbi, val, EP93XXFB_PIXELMODE);
225 return 0;
226}
227
228static void ep93xxfb_set_timing(struct fb_info *info)
229{
230 struct ep93xx_fbi *fbi = info->par;
231 unsigned int vlines_total, hclks_total, start, stop;
232
233 vlines_total = info->var.yres + info->var.upper_margin +
234 info->var.lower_margin + info->var.vsync_len - 1;
235
236 hclks_total = info->var.xres + info->var.left_margin +
237 info->var.right_margin + info->var.hsync_len - 1;
238
239 ep93xxfb_out_locked(fbi, vlines_total, EP93XXFB_VLINES_TOTAL);
240 ep93xxfb_out_locked(fbi, hclks_total, EP93XXFB_HCLKS_TOTAL);
241
242 start = vlines_total;
243 stop = vlines_total - info->var.vsync_len;
244 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VSYNC);
245
246 start = vlines_total - info->var.vsync_len - info->var.upper_margin;
247 stop = info->var.lower_margin - 1;
248 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VBLANK);
249 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VACTIVE);
250
251 start = vlines_total;
252 stop = vlines_total + 1;
253 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_VCLK);
254
255 start = hclks_total;
256 stop = hclks_total - info->var.hsync_len;
257 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HSYNC);
258
259 start = hclks_total - info->var.hsync_len - info->var.left_margin;
260 stop = info->var.right_margin - 1;
261 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HBLANK);
262 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HACTIVE);
263
264 start = hclks_total;
265 stop = hclks_total;
266 ep93xxfb_out_locked(fbi, start | (stop << 16), EP93XXFB_HCLK);
267
268 ep93xxfb_out_locked(fbi, 0x0, EP93XXFB_LINE_CARRY);
269}
270
271static int ep93xxfb_set_par(struct fb_info *info)
272{
273 struct ep93xx_fbi *fbi = info->par;
274
275 clk_set_rate(fbi->clk, 1000 * PICOS2KHZ(info->var.pixclock));
276
277 ep93xxfb_set_timing(info);
278
279 info->fix.line_length = info->var.xres_virtual *
280 info->var.bits_per_pixel / 8;
281
282 ep93xxfb_writel(fbi, info->fix.smem_start, EP93XXFB_SCREEN_PAGE);
283 ep93xxfb_writel(fbi, info->var.yres - 1, EP93XXFB_SCREEN_LINES);
284 ep93xxfb_writel(fbi, ((info->var.xres * info->var.bits_per_pixel)
285 / 32) - 1, EP93XXFB_LINE_LENGTH);
286 ep93xxfb_writel(fbi, info->fix.line_length / 4, EP93XXFB_VLINE_STEP);
287 ep93xxfb_set_video_attribs(info);
288 return 0;
289}
290
291static int ep93xxfb_check_var(struct fb_var_screeninfo *var,
292 struct fb_info *info)
293{
294 int err;
295
296 err = ep93xxfb_set_pixelmode(info);
297 if (err)
298 return err;
299
300 var->xres = max_t(unsigned int, var->xres, EP93XXFB_MIN_XRES);
301 var->xres = min_t(unsigned int, var->xres, EP93XXFB_MAX_XRES);
302 var->xres_virtual = max(var->xres_virtual, var->xres);
303
304 var->yres = max_t(unsigned int, var->yres, EP93XXFB_MIN_YRES);
305 var->yres = min_t(unsigned int, var->yres, EP93XXFB_MAX_YRES);
306 var->yres_virtual = max(var->yres_virtual, var->yres);
307
308 return 0;
309}
310
311static int ep93xxfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
312{
313 unsigned int offset = vma->vm_pgoff << PAGE_SHIFT;
314
315 if (offset < info->fix.smem_len) {
316 return dma_mmap_writecombine(info->dev, vma, info->screen_base,
317 info->fix.smem_start,
318 info->fix.smem_len);
319 }
320
321 return -EINVAL;
322}
323
324static int ep93xxfb_blank(int blank_mode, struct fb_info *info)
325{
326 struct ep93xx_fbi *fbi = info->par;
327 unsigned int attribs = ep93xxfb_readl(fbi, EP93XXFB_ATTRIBS);
328
329 if (blank_mode) {
330 if (fbi->mach_info->blank)
331 fbi->mach_info->blank(blank_mode, info);
332 ep93xxfb_out_locked(fbi, attribs & ~EP93XXFB_ENABLE,
333 EP93XXFB_ATTRIBS);
334 clk_disable(fbi->clk);
335 } else {
336 clk_enable(fbi->clk);
337 ep93xxfb_out_locked(fbi, attribs | EP93XXFB_ENABLE,
338 EP93XXFB_ATTRIBS);
339 if (fbi->mach_info->blank)
340 fbi->mach_info->blank(blank_mode, info);
341 }
342
343 return 0;
344}
345
346static inline int ep93xxfb_convert_color(int val, int width)
347{
348 return ((val << width) + 0x7fff - val) >> 16;
349}
350
351static int ep93xxfb_setcolreg(unsigned int regno, unsigned int red,
352 unsigned int green, unsigned int blue,
353 unsigned int transp, struct fb_info *info)
354{
355 struct ep93xx_fbi *fbi = info->par;
356 unsigned int *pal = info->pseudo_palette;
357 unsigned int ctrl, i, rgb, lut_current, lut_stat;
358
359 switch (info->fix.visual) {
360 case FB_VISUAL_PSEUDOCOLOR:
361 rgb = ((red & 0xff00) << 8) | (green & 0xff00) |
362 ((blue & 0xff00) >> 8);
363
364 pal[regno] = rgb;
365 ep93xxfb_writel(fbi, rgb, (EP93XXFB_COLOR_LUT + (regno << 2)));
366 ctrl = ep93xxfb_readl(fbi, EP93XXFB_LUT_SW_CONTROL);
367 lut_stat = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SSTAT);
368 lut_current = !!(ctrl & EP93XXFB_LUT_SW_CONTROL_SWTCH);
369
370 if (lut_stat == lut_current) {
371 for (i = 0; i < 256; i++) {
372 ep93xxfb_writel(fbi, pal[i],
373 EP93XXFB_COLOR_LUT + (i << 2));
374 }
375
376 ep93xxfb_writel(fbi,
377 ctrl ^ EP93XXFB_LUT_SW_CONTROL_SWTCH,
378 EP93XXFB_LUT_SW_CONTROL);
379 }
380 break;
381
382 case FB_VISUAL_TRUECOLOR:
383 if (regno > 16)
384 return 1;
385
386 red = ep93xxfb_convert_color(red, info->var.red.length);
387 green = ep93xxfb_convert_color(green, info->var.green.length);
388 blue = ep93xxfb_convert_color(blue, info->var.blue.length);
389 transp = ep93xxfb_convert_color(transp,
390 info->var.transp.length);
391
392 pal[regno] = (red << info->var.red.offset) |
393 (green << info->var.green.offset) |
394 (blue << info->var.blue.offset) |
395 (transp << info->var.transp.offset);
396 break;
397
398 default:
399 return 1;
400 }
401
402 return 0;
403}
404
405static struct fb_ops ep93xxfb_ops = {
406 .owner = THIS_MODULE,
407 .fb_check_var = ep93xxfb_check_var,
408 .fb_set_par = ep93xxfb_set_par,
409 .fb_blank = ep93xxfb_blank,
410 .fb_fillrect = cfb_fillrect,
411 .fb_copyarea = cfb_copyarea,
412 .fb_imageblit = cfb_imageblit,
413 .fb_setcolreg = ep93xxfb_setcolreg,
414 .fb_mmap = ep93xxfb_mmap,
415};
416
417static int __init ep93xxfb_calc_fbsize(struct ep93xxfb_mach_info *mach_info)
418{
419 int i, fb_size = 0;
420
421 if (mach_info->num_modes == EP93XXFB_USE_MODEDB) {
422 fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES *
423 mach_info->bpp / 8;
424 } else {
425 for (i = 0; i < mach_info->num_modes; i++) {
426 const struct fb_videomode *mode;
427 int size;
428
429 mode = &mach_info->modes[i];
430 size = mode->xres * mode->yres * mach_info->bpp / 8;
431 if (size > fb_size)
432 fb_size = size;
433 }
434 }
435
436 return fb_size;
437}
438
439static int __init ep93xxfb_alloc_videomem(struct fb_info *info)
440{
441 struct ep93xx_fbi *fbi = info->par;
442 char __iomem *virt_addr;
443 dma_addr_t phys_addr;
444 unsigned int fb_size;
445
446 fb_size = ep93xxfb_calc_fbsize(fbi->mach_info);
447 virt_addr = dma_alloc_writecombine(info->dev, fb_size,
448 &phys_addr, GFP_KERNEL);
449 if (!virt_addr)
450 return -ENOMEM;
451
452 /*
453 * There is a bug in the ep93xx framebuffer which causes problems
454 * if bit 27 of the physical address is set.
455 * See: http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
456 * There does not seem to be any offical errata for this, but I
457 * have confirmed the problem exists on my hardware (ep9315) at
458 * least.
459 */
460 if (check_screenpage_bug && phys_addr & (1 << 27)) {
461 dev_err(info->dev, "ep93xx framebuffer bug. phys addr (0x%x) "
462 "has bit 27 set: cannot init framebuffer\n",
463 phys_addr);
464
465 dma_free_coherent(info->dev, fb_size, virt_addr, phys_addr);
466 return -ENOMEM;
467 }
468
469 info->fix.smem_start = phys_addr;
470 info->fix.smem_len = fb_size;
471 info->screen_base = virt_addr;
472
473 return 0;
474}
475
476static void ep93xxfb_dealloc_videomem(struct fb_info *info)
477{
478 if (info->screen_base)
479 dma_free_coherent(info->dev, info->fix.smem_len,
480 info->screen_base, info->fix.smem_start);
481}
482
483static int __init ep93xxfb_probe(struct platform_device *pdev)
484{
485 struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data;
486 struct fb_info *info;
487 struct ep93xx_fbi *fbi;
488 struct resource *res;
489 char *video_mode;
490 int err;
491
492 if (!mach_info)
493 return -EINVAL;
494
495 info = framebuffer_alloc(sizeof(struct ep93xx_fbi), &pdev->dev);
496 if (!info)
497 return -ENOMEM;
498
499 info->dev = &pdev->dev;
500 platform_set_drvdata(pdev, info);
501 fbi = info->par;
502 fbi->mach_info = mach_info;
503
504 err = fb_alloc_cmap(&info->cmap, 256, 0);
505 if (err)
506 goto failed;
507
508 err = ep93xxfb_alloc_videomem(info);
509 if (err)
510 goto failed;
511
512 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
513 if (!res) {
514 err = -ENXIO;
515 goto failed;
516 }
517
518 res = request_mem_region(res->start, resource_size(res), pdev->name);
519 if (!res) {
520 err = -EBUSY;
521 goto failed;
522 }
523
524 fbi->res = res;
525 fbi->mmio_base = ioremap(res->start, resource_size(res));
526 if (!fbi->mmio_base) {
527 err = -ENXIO;
528 goto failed;
529 }
530
531 strcpy(info->fix.id, pdev->name);
532 info->fbops = &ep93xxfb_ops;
533 info->fix.type = FB_TYPE_PACKED_PIXELS;
534 info->fix.accel = FB_ACCEL_NONE;
535 info->var.activate = FB_ACTIVATE_NOW;
536 info->var.vmode = FB_VMODE_NONINTERLACED;
537 info->flags = FBINFO_DEFAULT;
538 info->node = -1;
539 info->state = FBINFO_STATE_RUNNING;
540 info->pseudo_palette = &fbi->pseudo_palette;
541
542 fb_get_options("ep93xx-fb", &video_mode);
543 err = fb_find_mode(&info->var, info, video_mode,
544 fbi->mach_info->modes, fbi->mach_info->num_modes,
545 fbi->mach_info->default_mode, fbi->mach_info->bpp);
546 if (err == 0) {
547 dev_err(info->dev, "No suitable video mode found\n");
548 err = -EINVAL;
549 goto failed;
550 }
551
552 if (mach_info->setup) {
553 err = mach_info->setup(pdev);
554 if (err)
555 return err;
556 }
557
558 err = ep93xxfb_check_var(&info->var, info);
559 if (err)
560 goto failed;
561
562 fbi->clk = clk_get(info->dev, NULL);
563 if (IS_ERR(fbi->clk)) {
564 err = PTR_ERR(fbi->clk);
565 fbi->clk = NULL;
566 goto failed;
567 }
568
569 ep93xxfb_set_par(info);
570 clk_enable(fbi->clk);
571
572 err = register_framebuffer(info);
573 if (err)
574 goto failed;
575
576 dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
577 info->var.xres, info->var.yres, info->var.bits_per_pixel);
578 return 0;
579
580failed:
581 if (fbi->clk)
582 clk_put(fbi->clk);
583 if (fbi->mmio_base)
584 iounmap(fbi->mmio_base);
585 if (fbi->res)
586 release_mem_region(fbi->res->start, resource_size(fbi->res));
587 ep93xxfb_dealloc_videomem(info);
588 if (&info->cmap)
589 fb_dealloc_cmap(&info->cmap);
590 if (fbi->mach_info->teardown)
591 fbi->mach_info->teardown(pdev);
592 kfree(info);
593 platform_set_drvdata(pdev, NULL);
594
595 return err;
596}
597
598static int ep93xxfb_remove(struct platform_device *pdev)
599{
600 struct fb_info *info = platform_get_drvdata(pdev);
601 struct ep93xx_fbi *fbi = info->par;
602
603 unregister_framebuffer(info);
604 clk_disable(fbi->clk);
605 clk_put(fbi->clk);
606 iounmap(fbi->mmio_base);
607 release_mem_region(fbi->res->start, resource_size(fbi->res));
608 ep93xxfb_dealloc_videomem(info);
609 fb_dealloc_cmap(&info->cmap);
610
611 if (fbi->mach_info->teardown)
612 fbi->mach_info->teardown(pdev);
613
614 kfree(info);
615 platform_set_drvdata(pdev, NULL);
616
617 return 0;
618}
619
620static struct platform_driver ep93xxfb_driver = {
621 .probe = ep93xxfb_probe,
622 .remove = ep93xxfb_remove,
623 .driver = {
624 .name = "ep93xx-fb",
625 .owner = THIS_MODULE,
626 },
627};
628
629static int __devinit ep93xxfb_init(void)
630{
631 return platform_driver_register(&ep93xxfb_driver);
632}
633
634static void __exit ep93xxfb_exit(void)
635{
636 platform_driver_unregister(&ep93xxfb_driver);
637}
638
639module_init(ep93xxfb_init);
640module_exit(ep93xxfb_exit);
641
642MODULE_DESCRIPTION("EP93XX Framebuffer Driver");
643MODULE_ALIAS("platform:ep93xx-fb");
644MODULE_AUTHOR("Ryan Mallon <ryan&bluewatersys.com>, "
645 "H Hartley Sweeten <hsweeten@visionengravers.com");
646MODULE_LICENSE("GPL");
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 0a7a6679ee6e..c27ab1ed9604 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -125,7 +125,7 @@ page_already_added:
125 return 0; 125 return 0;
126} 126}
127 127
128static struct vm_operations_struct fb_deferred_io_vm_ops = { 128static const struct vm_operations_struct fb_deferred_io_vm_ops = {
129 .fault = fb_deferred_io_fault, 129 .fault = fb_deferred_io_fault,
130 .page_mkwrite = fb_deferred_io_mkwrite, 130 .page_mkwrite = fb_deferred_io_mkwrite,
131}; 131};
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index f8a09bf8d0cd..99bbd282ce63 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -16,7 +16,6 @@
16#include <linux/compat.h> 16#include <linux/compat.h>
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/smp_lock.h>
20#include <linux/kernel.h> 19#include <linux/kernel.h>
21#include <linux/major.h> 20#include <linux/major.h>
22#include <linux/slab.h> 21#include <linux/slab.h>
@@ -872,8 +871,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
872 err = -EINVAL; 871 err = -EINVAL;
873 872
874 if (err || !info->fbops->fb_pan_display || 873 if (err || !info->fbops->fb_pan_display ||
875 var->yoffset + yres > info->var.yres_virtual || 874 var->yoffset > info->var.yres_virtual - yres ||
876 var->xoffset + info->var.xres > info->var.xres_virtual) 875 var->xoffset > info->var.xres_virtual - info->var.xres)
877 return -EINVAL; 876 return -EINVAL;
878 877
879 if ((err = info->fbops->fb_pan_display(var, info))) 878 if ((err = info->fbops->fb_pan_display(var, info)))
@@ -955,6 +954,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
955 goto done; 954 goto done;
956 955
957 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { 956 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
957 struct fb_var_screeninfo old_var;
958 struct fb_videomode mode; 958 struct fb_videomode mode;
959 959
960 if (info->fbops->fb_get_caps) { 960 if (info->fbops->fb_get_caps) {
@@ -964,10 +964,20 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
964 goto done; 964 goto done;
965 } 965 }
966 966
967 old_var = info->var;
967 info->var = *var; 968 info->var = *var;
968 969
969 if (info->fbops->fb_set_par) 970 if (info->fbops->fb_set_par) {
970 info->fbops->fb_set_par(info); 971 ret = info->fbops->fb_set_par(info);
972
973 if (ret) {
974 info->var = old_var;
975 printk(KERN_WARNING "detected "
976 "fb_set_par error, "
977 "error code: %d\n", ret);
978 goto done;
979 }
980 }
971 981
972 fb_pan_display(info, &info->var); 982 fb_pan_display(info, &info->var);
973 fb_set_cmap(&info->cmap, info); 983 fb_set_cmap(&info->cmap, info);
@@ -1310,8 +1320,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
1310 1320
1311static int 1321static int
1312fb_mmap(struct file *file, struct vm_area_struct * vma) 1322fb_mmap(struct file *file, struct vm_area_struct * vma)
1313__acquires(&info->lock)
1314__releases(&info->lock)
1315{ 1323{
1316 int fbidx = iminor(file->f_path.dentry->d_inode); 1324 int fbidx = iminor(file->f_path.dentry->d_inode);
1317 struct fb_info *info = registered_fb[fbidx]; 1325 struct fb_info *info = registered_fb[fbidx];
@@ -1325,16 +1333,14 @@ __releases(&info->lock)
1325 off = vma->vm_pgoff << PAGE_SHIFT; 1333 off = vma->vm_pgoff << PAGE_SHIFT;
1326 if (!fb) 1334 if (!fb)
1327 return -ENODEV; 1335 return -ENODEV;
1336 mutex_lock(&info->mm_lock);
1328 if (fb->fb_mmap) { 1337 if (fb->fb_mmap) {
1329 int res; 1338 int res;
1330 mutex_lock(&info->lock);
1331 res = fb->fb_mmap(info, vma); 1339 res = fb->fb_mmap(info, vma);
1332 mutex_unlock(&info->lock); 1340 mutex_unlock(&info->mm_lock);
1333 return res; 1341 return res;
1334 } 1342 }
1335 1343
1336 mutex_lock(&info->lock);
1337
1338 /* frame buffer memory */ 1344 /* frame buffer memory */
1339 start = info->fix.smem_start; 1345 start = info->fix.smem_start;
1340 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); 1346 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
@@ -1342,13 +1348,13 @@ __releases(&info->lock)
1342 /* memory mapped io */ 1348 /* memory mapped io */
1343 off -= len; 1349 off -= len;
1344 if (info->var.accel_flags) { 1350 if (info->var.accel_flags) {
1345 mutex_unlock(&info->lock); 1351 mutex_unlock(&info->mm_lock);
1346 return -EINVAL; 1352 return -EINVAL;
1347 } 1353 }
1348 start = info->fix.mmio_start; 1354 start = info->fix.mmio_start;
1349 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); 1355 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
1350 } 1356 }
1351 mutex_unlock(&info->lock); 1357 mutex_unlock(&info->mm_lock);
1352 start &= PAGE_MASK; 1358 start &= PAGE_MASK;
1353 if ((vma->vm_end - vma->vm_start + off) > len) 1359 if ((vma->vm_end - vma->vm_start + off) > len)
1354 return -EINVAL; 1360 return -EINVAL;
@@ -1518,6 +1524,7 @@ register_framebuffer(struct fb_info *fb_info)
1518 break; 1524 break;
1519 fb_info->node = i; 1525 fb_info->node = i;
1520 mutex_init(&fb_info->lock); 1526 mutex_init(&fb_info->lock);
1527 mutex_init(&fb_info->mm_lock);
1521 1528
1522 fb_info->dev = device_create(fb_class, fb_info->device, 1529 fb_info->dev = device_create(fb_class, fb_info->device,
1523 MKDEV(FB_MAJOR, i), NULL, "fb%d", i); 1530 MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
@@ -1793,7 +1800,7 @@ static int __init video_setup(char *options)
1793 global = 1; 1800 global = 1;
1794 } 1801 }
1795 1802
1796 if (!global && !strstr(options, "fb:")) { 1803 if (!global && !strchr(options, ':')) {
1797 fb_mode_option = options; 1804 fb_mode_option = options;
1798 global = 1; 1805 global = 1;
1799 } 1806 }
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 5c1a2c01778f..9ae9cd32bd06 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -256,8 +256,8 @@ static void fix_edid(unsigned char *edid, int fix)
256 256
257static int edid_checksum(unsigned char *edid) 257static int edid_checksum(unsigned char *edid)
258{ 258{
259 unsigned char i, csum = 0, all_null = 0; 259 unsigned char csum = 0, all_null = 0;
260 int err = 0, fix = check_edid(edid); 260 int i, err = 0, fix = check_edid(edid);
261 261
262 if (fix) 262 if (fix)
263 fix_edid(edid, fix); 263 fix_edid(edid, fix);
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index f153c581cbd7..72d68b3dc478 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info)
750static int map_video_memory(struct fb_info *info) 750static int map_video_memory(struct fb_info *info)
751{ 751{
752 phys_addr_t phys; 752 phys_addr_t phys;
753 u32 smem_len = info->fix.line_length * info->var.yres_virtual;
753 754
754 pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); 755 pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual);
755 pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); 756 pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
756 pr_debug("info->fix.line_length = %d\n", info->fix.line_length); 757 pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
758 pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len);
757 759
758 info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; 760 info->screen_base = fsl_diu_alloc(smem_len, &phys);
759 pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len);
760 info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys);
761 if (info->screen_base == NULL) { 761 if (info->screen_base == NULL) {
762 printk(KERN_ERR "Unable to allocate fb memory\n"); 762 printk(KERN_ERR "Unable to allocate fb memory\n");
763 return -ENOMEM; 763 return -ENOMEM;
764 } 764 }
765 mutex_lock(&info->mm_lock);
765 info->fix.smem_start = (unsigned long) phys; 766 info->fix.smem_start = (unsigned long) phys;
767 info->fix.smem_len = smem_len;
768 mutex_unlock(&info->mm_lock);
766 info->screen_size = info->fix.smem_len; 769 info->screen_size = info->fix.smem_len;
767 770
768 pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", 771 pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n",
769 info->fix.smem_start, 772 info->fix.smem_start, info->fix.smem_len);
770 info->fix.smem_len);
771 pr_debug("screen base %p\n", info->screen_base); 773 pr_debug("screen base %p\n", info->screen_base);
772 774
773 return 0; 775 return 0;
@@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info)
776static void unmap_video_memory(struct fb_info *info) 778static void unmap_video_memory(struct fb_info *info)
777{ 779{
778 fsl_diu_free(info->screen_base, info->fix.smem_len); 780 fsl_diu_free(info->screen_base, info->fix.smem_len);
781 mutex_lock(&info->mm_lock);
779 info->screen_base = NULL; 782 info->screen_base = NULL;
780 info->fix.smem_start = 0; 783 info->fix.smem_start = 0;
781 info->fix.smem_len = 0; 784 info->fix.smem_len = 0;
785 mutex_unlock(&info->mm_lock);
782} 786}
783 787
784/* 788/*
@@ -1219,12 +1223,6 @@ static int __devinit install_fb(struct fb_info *info)
1219 return -EINVAL; 1223 return -EINVAL;
1220 } 1224 }
1221 1225
1222 if (fsl_diu_set_par(info)) {
1223 printk(KERN_ERR "fb_set_par failed");
1224 fb_dealloc_cmap(&info->cmap);
1225 return -EINVAL;
1226 }
1227
1228 if (register_framebuffer(info) < 0) { 1226 if (register_framebuffer(info) < 0) {
1229 printk(KERN_ERR "register_framebuffer failed"); 1227 printk(KERN_ERR "register_framebuffer failed");
1230 unmap_video_memory(info); 1228 unmap_video_memory(info);
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 020db7fc9153..e7116a6d82d3 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -44,9 +44,6 @@ static struct fb_fix_screeninfo hitfb_fix __initdata = {
44 .accel = FB_ACCEL_NONE, 44 .accel = FB_ACCEL_NONE,
45}; 45};
46 46
47static u32 pseudo_palette[16];
48static struct fb_info fb_info;
49
50static inline void hitfb_accel_wait(void) 47static inline void hitfb_accel_wait(void)
51{ 48{
52 while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ; 49 while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ;
@@ -331,6 +328,8 @@ static struct fb_ops hitfb_ops = {
331static int __init hitfb_probe(struct platform_device *dev) 328static int __init hitfb_probe(struct platform_device *dev)
332{ 329{
333 unsigned short lcdclor, ldr3, ldvndr; 330 unsigned short lcdclor, ldr3, ldvndr;
331 struct fb_info *info;
332 int ret;
334 333
335 if (fb_get_options("hitfb", NULL)) 334 if (fb_get_options("hitfb", NULL))
336 return -ENODEV; 335 return -ENODEV;
@@ -384,32 +383,53 @@ static int __init hitfb_probe(struct platform_device *dev)
384 break; 383 break;
385 } 384 }
386 385
387 fb_info.fbops = &hitfb_ops; 386 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
388 fb_info.var = hitfb_var; 387 if (unlikely(!info))
389 fb_info.fix = hitfb_fix; 388 return -ENOMEM;
390 fb_info.pseudo_palette = pseudo_palette; 389
391 fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | 390 info->fbops = &hitfb_ops;
391 info->var = hitfb_var;
392 info->fix = hitfb_fix;
393 info->pseudo_palette = info->par;
394 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
392 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; 395 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
393 396
394 fb_info.screen_base = (void *)hitfb_fix.smem_start; 397 info->screen_base = (void *)hitfb_fix.smem_start;
395 398
396 fb_alloc_cmap(&fb_info.cmap, 256, 0); 399 ret = fb_alloc_cmap(&info->cmap, 256, 0);
400 if (unlikely(ret < 0))
401 goto err_fb;
397 402
398 if (register_framebuffer(&fb_info) < 0) 403 ret = register_framebuffer(info);
399 return -EINVAL; 404 if (unlikely(ret < 0))
405 goto err;
406
407 platform_set_drvdata(dev, info);
400 408
401 printk(KERN_INFO "fb%d: %s frame buffer device\n", 409 printk(KERN_INFO "fb%d: %s frame buffer device\n",
402 fb_info.node, fb_info.fix.id); 410 info->node, info->fix.id);
411
403 return 0; 412 return 0;
413
414err:
415 fb_dealloc_cmap(&info->cmap);
416err_fb:
417 framebuffer_release(info);
418 return ret;
404} 419}
405 420
406static int __exit hitfb_remove(struct platform_device *dev) 421static int __exit hitfb_remove(struct platform_device *dev)
407{ 422{
408 return unregister_framebuffer(&fb_info); 423 struct fb_info *info = platform_get_drvdata(dev);
424
425 unregister_framebuffer(info);
426 fb_dealloc_cmap(&info->cmap);
427 framebuffer_release(info);
428
429 return 0;
409} 430}
410 431
411#ifdef CONFIG_PM 432static int hitfb_suspend(struct device *dev)
412static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
413{ 433{
414 u16 v; 434 u16 v;
415 435
@@ -421,7 +441,7 @@ static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
421 return 0; 441 return 0;
422} 442}
423 443
424static int hitfb_resume(struct platform_device *dev) 444static int hitfb_resume(struct device *dev)
425{ 445{
426 u16 v; 446 u16 v;
427 447
@@ -435,17 +455,19 @@ static int hitfb_resume(struct platform_device *dev)
435 455
436 return 0; 456 return 0;
437} 457}
438#endif 458
459static struct dev_pm_ops hitfb_dev_pm_ops = {
460 .suspend = hitfb_suspend,
461 .resume = hitfb_resume,
462};
439 463
440static struct platform_driver hitfb_driver = { 464static struct platform_driver hitfb_driver = {
441 .probe = hitfb_probe, 465 .probe = hitfb_probe,
442 .remove = __exit_p(hitfb_remove), 466 .remove = __exit_p(hitfb_remove),
443#ifdef CONFIG_PM
444 .suspend = hitfb_suspend,
445 .resume = hitfb_resume,
446#endif
447 .driver = { 467 .driver = {
448 .name = "hitfb", 468 .name = "hitfb",
469 .owner = THIS_MODULE,
470 .pm = &hitfb_dev_pm_ops,
449 }, 471 },
450}; 472};
451 473
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 2e940199fc89..5743ea25e818 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
1090 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 1090 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1091 1091
1092 strcpy(fix->id, "I810"); 1092 strcpy(fix->id, "I810");
1093 mutex_lock(&info->mm_lock);
1093 fix->smem_start = par->fb.physical; 1094 fix->smem_start = par->fb.physical;
1094 fix->smem_len = par->fb.size; 1095 fix->smem_len = par->fb.size;
1096 mutex_unlock(&info->mm_lock);
1095 fix->type = FB_TYPE_PACKED_PIXELS; 1097 fix->type = FB_TYPE_PACKED_PIXELS;
1096 fix->type_aux = 0; 1098 fix->type_aux = 0;
1097 fix->xpanstep = 8; 1099 fix->xpanstep = 8;
@@ -2058,8 +2060,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
2058 2060
2059 fb_var_to_videomode(&mode, &info->var); 2061 fb_var_to_videomode(&mode, &info->var);
2060 fb_add_videomode(&mode, &info->modelist); 2062 fb_add_videomode(&mode, &info->modelist);
2061 encode_fix(&info->fix, info); 2063
2062
2063 i810fb_init_ringbuffer(info); 2064 i810fb_init_ringbuffer(info);
2064 err = register_framebuffer(info); 2065 err = register_framebuffer(info);
2065 2066
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 15a0ee6d8e23..66358fa825f3 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -33,6 +33,7 @@
33#include <linux/math64.h> 33#include <linux/math64.h>
34 34
35#include <mach/imxfb.h> 35#include <mach/imxfb.h>
36#include <mach/hardware.h>
36 37
37/* 38/*
38 * Complain if VAR is out of range. 39 * Complain if VAR is out of range.
@@ -129,6 +130,10 @@
129#define LCDISR_EOF (1<<1) 130#define LCDISR_EOF (1<<1)
130#define LCDISR_BOF (1<<0) 131#define LCDISR_BOF (1<<0)
131 132
133/* Used fb-mode. Can be set on kernel command line, therefore file-static. */
134static const char *fb_mode;
135
136
132/* 137/*
133 * These are the bitfields for each 138 * These are the bitfields for each
134 * display depth that we support. 139 * display depth that we support.
@@ -145,10 +150,6 @@ struct imxfb_info {
145 void __iomem *regs; 150 void __iomem *regs;
146 struct clk *clk; 151 struct clk *clk;
147 152
148 u_int max_bpp;
149 u_int max_xres;
150 u_int max_yres;
151
152 /* 153 /*
153 * These are the addresses we mapped 154 * These are the addresses we mapped
154 * the framebuffer memory region to. 155 * the framebuffer memory region to.
@@ -172,6 +173,9 @@ struct imxfb_info {
172 cmap_static:1, 173 cmap_static:1,
173 unused:30; 174 unused:30;
174 175
176 struct imx_fb_videomode *mode;
177 int num_modes;
178
175 void (*lcd_power)(int); 179 void (*lcd_power)(int);
176 void (*backlight_power)(int); 180 void (*backlight_power)(int);
177}; 181};
@@ -298,6 +302,18 @@ static int imxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
298 return ret; 302 return ret;
299} 303}
300 304
305static const struct imx_fb_videomode *imxfb_find_mode(struct imxfb_info *fbi)
306{
307 struct imx_fb_videomode *m;
308 int i;
309
310 for (i = 0, m = &fbi->mode[0]; i < fbi->num_modes; i++, m++) {
311 if (!strcmp(m->mode.name, fb_mode))
312 return m;
313 }
314 return NULL;
315}
316
301/* 317/*
302 * imxfb_check_var(): 318 * imxfb_check_var():
303 * Round up in the following order: bits_per_pixel, xres, 319 * Round up in the following order: bits_per_pixel, xres,
@@ -308,35 +324,81 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
308{ 324{
309 struct imxfb_info *fbi = info->par; 325 struct imxfb_info *fbi = info->par;
310 struct imxfb_rgb *rgb; 326 struct imxfb_rgb *rgb;
327 const struct imx_fb_videomode *imxfb_mode;
328 unsigned long lcd_clk;
329 unsigned long long tmp;
330 u32 pcr = 0;
311 331
312 if (var->xres < MIN_XRES) 332 if (var->xres < MIN_XRES)
313 var->xres = MIN_XRES; 333 var->xres = MIN_XRES;
314 if (var->yres < MIN_YRES) 334 if (var->yres < MIN_YRES)
315 var->yres = MIN_YRES; 335 var->yres = MIN_YRES;
316 if (var->xres > fbi->max_xres) 336
317 var->xres = fbi->max_xres; 337 imxfb_mode = imxfb_find_mode(fbi);
318 if (var->yres > fbi->max_yres) 338 if (!imxfb_mode)
319 var->yres = fbi->max_yres; 339 return -EINVAL;
320 var->xres_virtual = max(var->xres_virtual, var->xres); 340
321 var->yres_virtual = max(var->yres_virtual, var->yres); 341 var->xres = imxfb_mode->mode.xres;
342 var->yres = imxfb_mode->mode.yres;
343 var->bits_per_pixel = imxfb_mode->bpp;
344 var->pixclock = imxfb_mode->mode.pixclock;
345 var->hsync_len = imxfb_mode->mode.hsync_len;
346 var->left_margin = imxfb_mode->mode.left_margin;
347 var->right_margin = imxfb_mode->mode.right_margin;
348 var->vsync_len = imxfb_mode->mode.vsync_len;
349 var->upper_margin = imxfb_mode->mode.upper_margin;
350 var->lower_margin = imxfb_mode->mode.lower_margin;
351 var->sync = imxfb_mode->mode.sync;
352 var->xres_virtual = max(var->xres_virtual, var->xres);
353 var->yres_virtual = max(var->yres_virtual, var->yres);
322 354
323 pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel); 355 pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
356
357 lcd_clk = clk_get_rate(fbi->clk);
358
359 tmp = var->pixclock * (unsigned long long)lcd_clk;
360
361 do_div(tmp, 1000000);
362
363 if (do_div(tmp, 1000000) > 500000)
364 tmp++;
365
366 pcr = (unsigned int)tmp;
367
368 if (--pcr > 0x3F) {
369 pcr = 0x3F;
370 printk(KERN_WARNING "Must limit pixel clock to %luHz\n",
371 lcd_clk / pcr);
372 }
373
324 switch (var->bits_per_pixel) { 374 switch (var->bits_per_pixel) {
325 case 32: 375 case 32:
376 pcr |= PCR_BPIX_18;
326 rgb = &def_rgb_18; 377 rgb = &def_rgb_18;
327 break; 378 break;
328 case 16: 379 case 16:
329 default: 380 default:
330 if (fbi->pcr & PCR_TFT) 381 if (cpu_is_mx1())
382 pcr |= PCR_BPIX_12;
383 else
384 pcr |= PCR_BPIX_16;
385
386 if (imxfb_mode->pcr & PCR_TFT)
331 rgb = &def_rgb_16_tft; 387 rgb = &def_rgb_16_tft;
332 else 388 else
333 rgb = &def_rgb_16_stn; 389 rgb = &def_rgb_16_stn;
334 break; 390 break;
335 case 8: 391 case 8:
392 pcr |= PCR_BPIX_8;
336 rgb = &def_rgb_8; 393 rgb = &def_rgb_8;
337 break; 394 break;
338 } 395 }
339 396
397 /* add sync polarities */
398 pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
399
400 fbi->pcr = pcr;
401
340 /* 402 /*
341 * Copy the RGB parameters for this display 403 * Copy the RGB parameters for this display
342 * from the machine specific parameters. 404 * from the machine specific parameters.
@@ -393,10 +455,6 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
393 455
394 writel(fbi->screen_dma, fbi->regs + LCDC_SSA); 456 writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
395 457
396 /* physical screen start address */
397 writel(VPW_VPW(fbi->max_xres * fbi->max_bpp / 8 / 4),
398 fbi->regs + LCDC_VPW);
399
400 /* panning offset 0 (0 pixel offset) */ 458 /* panning offset 0 (0 pixel offset) */
401 writel(0x00000000, fbi->regs + LCDC_POS); 459 writel(0x00000000, fbi->regs + LCDC_POS);
402 460
@@ -468,8 +526,6 @@ static struct fb_ops imxfb_ops = {
468static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info) 526static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
469{ 527{
470 struct imxfb_info *fbi = info->par; 528 struct imxfb_info *fbi = info->par;
471 unsigned int pcr, lcd_clk;
472 unsigned long long tmp;
473 529
474 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", 530 pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
475 var->xres, var->hsync_len, 531 var->xres, var->hsync_len,
@@ -505,6 +561,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
505 info->fix.id, var->lower_margin); 561 info->fix.id, var->lower_margin);
506#endif 562#endif
507 563
564 /* physical screen start address */
565 writel(VPW_VPW(var->xres * var->bits_per_pixel / 8 / 4),
566 fbi->regs + LCDC_VPW);
567
508 writel(HCR_H_WIDTH(var->hsync_len - 1) | 568 writel(HCR_H_WIDTH(var->hsync_len - 1) |
509 HCR_H_WAIT_1(var->right_margin - 1) | 569 HCR_H_WAIT_1(var->right_margin - 1) |
510 HCR_H_WAIT_2(var->left_margin - 3), 570 HCR_H_WAIT_2(var->left_margin - 3),
@@ -518,22 +578,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
518 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres), 578 writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
519 fbi->regs + LCDC_SIZE); 579 fbi->regs + LCDC_SIZE);
520 580
521 lcd_clk = clk_get_rate(fbi->clk); 581 writel(fbi->pcr, fbi->regs + LCDC_PCR);
522 tmp = var->pixclock * (unsigned long long)lcd_clk;
523 do_div(tmp, 1000000);
524 if (do_div(tmp, 1000000) > 500000)
525 tmp++;
526 pcr = (unsigned int)tmp;
527 if (--pcr > 0x3F) {
528 pcr = 0x3F;
529 printk(KERN_WARNING "Must limit pixel clock to %uHz\n",
530 lcd_clk / pcr);
531 }
532
533 /* add sync polarities */
534 pcr |= fbi->pcr & ~0x3F;
535
536 writel(pcr, fbi->regs + LCDC_PCR);
537 writel(fbi->pwmr, fbi->regs + LCDC_PWMR); 582 writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
538 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1); 583 writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
539 writel(fbi->dmacr, fbi->regs + LCDC_DMACR); 584 writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -575,6 +620,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
575 struct imx_fb_platform_data *pdata = pdev->dev.platform_data; 620 struct imx_fb_platform_data *pdata = pdev->dev.platform_data;
576 struct fb_info *info = dev_get_drvdata(&pdev->dev); 621 struct fb_info *info = dev_get_drvdata(&pdev->dev);
577 struct imxfb_info *fbi = info->par; 622 struct imxfb_info *fbi = info->par;
623 struct imx_fb_videomode *m;
624 int i;
578 625
579 pr_debug("%s\n",__func__); 626 pr_debug("%s\n",__func__);
580 627
@@ -603,35 +650,18 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev)
603 info->fbops = &imxfb_ops; 650 info->fbops = &imxfb_ops;
604 info->flags = FBINFO_FLAG_DEFAULT | 651 info->flags = FBINFO_FLAG_DEFAULT |
605 FBINFO_READS_FAST; 652 FBINFO_READS_FAST;
606
607 fbi->max_xres = pdata->xres;
608 info->var.xres = pdata->xres;
609 info->var.xres_virtual = pdata->xres;
610 fbi->max_yres = pdata->yres;
611 info->var.yres = pdata->yres;
612 info->var.yres_virtual = pdata->yres;
613 fbi->max_bpp = pdata->bpp;
614 info->var.bits_per_pixel = pdata->bpp;
615 info->var.nonstd = pdata->nonstd;
616 info->var.pixclock = pdata->pixclock;
617 info->var.hsync_len = pdata->hsync_len;
618 info->var.left_margin = pdata->left_margin;
619 info->var.right_margin = pdata->right_margin;
620 info->var.vsync_len = pdata->vsync_len;
621 info->var.upper_margin = pdata->upper_margin;
622 info->var.lower_margin = pdata->lower_margin;
623 info->var.sync = pdata->sync;
624 info->var.grayscale = pdata->cmap_greyscale; 653 info->var.grayscale = pdata->cmap_greyscale;
625 fbi->cmap_inverse = pdata->cmap_inverse; 654 fbi->cmap_inverse = pdata->cmap_inverse;
626 fbi->cmap_static = pdata->cmap_static; 655 fbi->cmap_static = pdata->cmap_static;
627 fbi->pcr = pdata->pcr;
628 fbi->lscr1 = pdata->lscr1; 656 fbi->lscr1 = pdata->lscr1;
629 fbi->dmacr = pdata->dmacr; 657 fbi->dmacr = pdata->dmacr;
630 fbi->pwmr = pdata->pwmr; 658 fbi->pwmr = pdata->pwmr;
631 fbi->lcd_power = pdata->lcd_power; 659 fbi->lcd_power = pdata->lcd_power;
632 fbi->backlight_power = pdata->backlight_power; 660 fbi->backlight_power = pdata->backlight_power;
633 info->fix.smem_len = fbi->max_xres * fbi->max_yres * 661
634 fbi->max_bpp / 8; 662 for (i = 0, m = &pdata->mode[0]; i < pdata->num_modes; i++, m++)
663 info->fix.smem_len = max_t(size_t, info->fix.smem_len,
664 m->mode.xres * m->mode.yres * m->bpp / 8);
635 665
636 return 0; 666 return 0;
637} 667}
@@ -642,9 +672,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
642 struct fb_info *info; 672 struct fb_info *info;
643 struct imx_fb_platform_data *pdata; 673 struct imx_fb_platform_data *pdata;
644 struct resource *res; 674 struct resource *res;
645 int ret; 675 int ret, i;
646 676
647 printk("i.MX Framebuffer driver\n"); 677 dev_info(&pdev->dev, "i.MX Framebuffer driver\n");
648 678
649 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 679 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
650 if (!res) 680 if (!res)
@@ -662,6 +692,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
662 692
663 fbi = info->par; 693 fbi = info->par;
664 694
695 if (!fb_mode)
696 fb_mode = pdata->mode[0].mode.name;
697
665 platform_set_drvdata(pdev, info); 698 platform_set_drvdata(pdev, info);
666 699
667 ret = imxfb_init_fbinfo(pdev); 700 ret = imxfb_init_fbinfo(pdev);
@@ -677,14 +710,14 @@ static int __init imxfb_probe(struct platform_device *pdev)
677 710
678 fbi->clk = clk_get(&pdev->dev, NULL); 711 fbi->clk = clk_get(&pdev->dev, NULL);
679 if (IS_ERR(fbi->clk)) { 712 if (IS_ERR(fbi->clk)) {
680 ret = PTR_ERR(fbi->clk);; 713 ret = PTR_ERR(fbi->clk);
681 dev_err(&pdev->dev, "unable to get clock: %d\n", ret); 714 dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
682 goto failed_getclock; 715 goto failed_getclock;
683 } 716 }
684 717
685 fbi->regs = ioremap(res->start, resource_size(res)); 718 fbi->regs = ioremap(res->start, resource_size(res));
686 if (fbi->regs == NULL) { 719 if (fbi->regs == NULL) {
687 printk(KERN_ERR"Cannot map frame buffer registers\n"); 720 dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
688 goto failed_ioremap; 721 goto failed_ioremap;
689 } 722 }
690 723
@@ -719,6 +752,13 @@ static int __init imxfb_probe(struct platform_device *pdev)
719 goto failed_platform_init; 752 goto failed_platform_init;
720 } 753 }
721 754
755 fbi->mode = pdata->mode;
756 fbi->num_modes = pdata->num_modes;
757
758 INIT_LIST_HEAD(&info->modelist);
759 for (i = 0; i < pdata->num_modes; i++)
760 fb_add_videomode(&pdata->mode[i].mode, &info->modelist);
761
722 /* 762 /*
723 * This makes sure that our colour bitfield 763 * This makes sure that our colour bitfield
724 * descriptors are correctly initialised. 764 * descriptors are correctly initialised.
@@ -754,7 +794,7 @@ failed_map:
754failed_getclock: 794failed_getclock:
755 iounmap(fbi->regs); 795 iounmap(fbi->regs);
756failed_ioremap: 796failed_ioremap:
757 release_mem_region(res->start, res->end - res->start); 797 release_mem_region(res->start, resource_size(res));
758failed_req: 798failed_req:
759 kfree(info->pseudo_palette); 799 kfree(info->pseudo_palette);
760failed_init: 800failed_init:
@@ -785,7 +825,7 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
785 framebuffer_release(info); 825 framebuffer_release(info);
786 826
787 iounmap(fbi->regs); 827 iounmap(fbi->regs);
788 release_mem_region(res->start, res->end - res->start + 1); 828 release_mem_region(res->start, resource_size(res));
789 clk_disable(fbi->clk); 829 clk_disable(fbi->clk);
790 clk_put(fbi->clk); 830 clk_put(fbi->clk);
791 831
@@ -811,8 +851,34 @@ static struct platform_driver imxfb_driver = {
811 }, 851 },
812}; 852};
813 853
854static int imxfb_setup(void)
855{
856#ifndef MODULE
857 char *opt, *options = NULL;
858
859 if (fb_get_options("imxfb", &options))
860 return -ENODEV;
861
862 if (!options || !*options)
863 return 0;
864
865 while ((opt = strsep(&options, ",")) != NULL) {
866 if (!*opt)
867 continue;
868 else
869 fb_mode = opt;
870 }
871#endif
872 return 0;
873}
874
814int __init imxfb_init(void) 875int __init imxfb_init(void)
815{ 876{
877 int ret = imxfb_setup();
878
879 if (ret < 0)
880 return ret;
881
816 return platform_driver_probe(&imxfb_driver, imxfb_probe); 882 return platform_driver_probe(&imxfb_driver, imxfb_probe);
817} 883}
818 884
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index d42346e7fdda..09f6e045d5be 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -25,16 +25,19 @@ static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) {
25 return (p & 0x40) ? fin : fin << ((p & 3) + 1); 25 return (p & 0x40) ? fin : fin << ((p & 3) + 1);
26} 26}
27 27
28static unsigned int g450_mnp2vco(CPMINFO unsigned int mnp) { 28static unsigned int g450_mnp2vco(const struct matrox_fb_info *minfo,
29 unsigned int mnp)
30{
29 unsigned int m, n; 31 unsigned int m, n;
30 32
31 m = ((mnp >> 16) & 0x0FF) + 1; 33 m = ((mnp >> 16) & 0x0FF) + 1;
32 n = ((mnp >> 7) & 0x1FE) + 4; 34 n = ((mnp >> 7) & 0x1FE) + 4;
33 return (ACCESS_FBINFO(features).pll.ref_freq * n + (m >> 1)) / m; 35 return (minfo->features.pll.ref_freq * n + (m >> 1)) / m;
34} 36}
35 37
36unsigned int g450_mnp2f(CPMINFO unsigned int mnp) { 38unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp)
37 return g450_vco2f(mnp, g450_mnp2vco(PMINFO mnp)); 39{
40 return g450_vco2f(mnp, g450_mnp2vco(minfo, mnp));
38} 41}
39 42
40static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) { 43static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
@@ -49,7 +52,10 @@ static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
49#define NO_MORE_MNP 0x01FFFFFF 52#define NO_MORE_MNP 0x01FFFFFF
50#define G450_MNP_FREQBITS (0xFFFFFF43) /* do not mask high byte so we'll catch NO_MORE_MNP */ 53#define G450_MNP_FREQBITS (0xFFFFFF43) /* do not mask high byte so we'll catch NO_MORE_MNP */
51 54
52static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* fvco, unsigned int mnp) { 55static unsigned int g450_nextpll(const struct matrox_fb_info *minfo,
56 const struct matrox_pll_limits *pi,
57 unsigned int *fvco, unsigned int mnp)
58{
53 unsigned int m, n, p; 59 unsigned int m, n, p;
54 unsigned int tvco = *fvco; 60 unsigned int tvco = *fvco;
55 61
@@ -90,12 +96,15 @@ static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, uns
90 } else { 96 } else {
91 m--; 97 m--;
92 } 98 }
93 n = ((tvco * (m+1) + ACCESS_FBINFO(features).pll.ref_freq) / (ACCESS_FBINFO(features).pll.ref_freq * 2)) - 2; 99 n = ((tvco * (m+1) + minfo->features.pll.ref_freq) / (minfo->features.pll.ref_freq * 2)) - 2;
94 } while (n < 0x03 || n > 0x7A); 100 } while (n < 0x03 || n > 0x7A);
95 return (m << 16) | (n << 8) | p; 101 return (m << 16) | (n << 8) | p;
96} 102}
97 103
98static unsigned int g450_firstpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* vco, unsigned int fout) { 104static unsigned int g450_firstpll(const struct matrox_fb_info *minfo,
105 const struct matrox_pll_limits *pi,
106 unsigned int *vco, unsigned int fout)
107{
99 unsigned int p; 108 unsigned int p;
100 unsigned int vcomax; 109 unsigned int vcomax;
101 110
@@ -121,88 +130,94 @@ static unsigned int g450_firstpll(CPMINFO const struct matrox_pll_limits* pi, un
121 } 130 }
122 *vco = tvco; 131 *vco = tvco;
123 } 132 }
124 return g450_nextpll(PMINFO pi, vco, 0xFF0000 | p); 133 return g450_nextpll(minfo, pi, vco, 0xFF0000 | p);
125} 134}
126 135
127static inline unsigned int g450_setpll(CPMINFO unsigned int mnp, unsigned int pll) { 136static inline unsigned int g450_setpll(const struct matrox_fb_info *minfo,
137 unsigned int mnp, unsigned int pll)
138{
128 switch (pll) { 139 switch (pll) {
129 case M_PIXEL_PLL_A: 140 case M_PIXEL_PLL_A:
130 matroxfb_DAC_out(PMINFO M1064_XPIXPLLAM, mnp >> 16); 141 matroxfb_DAC_out(minfo, M1064_XPIXPLLAM, mnp >> 16);
131 matroxfb_DAC_out(PMINFO M1064_XPIXPLLAN, mnp >> 8); 142 matroxfb_DAC_out(minfo, M1064_XPIXPLLAN, mnp >> 8);
132 matroxfb_DAC_out(PMINFO M1064_XPIXPLLAP, mnp); 143 matroxfb_DAC_out(minfo, M1064_XPIXPLLAP, mnp);
133 return M1064_XPIXPLLSTAT; 144 return M1064_XPIXPLLSTAT;
134 145
135 case M_PIXEL_PLL_B: 146 case M_PIXEL_PLL_B:
136 matroxfb_DAC_out(PMINFO M1064_XPIXPLLBM, mnp >> 16); 147 matroxfb_DAC_out(minfo, M1064_XPIXPLLBM, mnp >> 16);
137 matroxfb_DAC_out(PMINFO M1064_XPIXPLLBN, mnp >> 8); 148 matroxfb_DAC_out(minfo, M1064_XPIXPLLBN, mnp >> 8);
138 matroxfb_DAC_out(PMINFO M1064_XPIXPLLBP, mnp); 149 matroxfb_DAC_out(minfo, M1064_XPIXPLLBP, mnp);
139 return M1064_XPIXPLLSTAT; 150 return M1064_XPIXPLLSTAT;
140 151
141 case M_PIXEL_PLL_C: 152 case M_PIXEL_PLL_C:
142 matroxfb_DAC_out(PMINFO M1064_XPIXPLLCM, mnp >> 16); 153 matroxfb_DAC_out(minfo, M1064_XPIXPLLCM, mnp >> 16);
143 matroxfb_DAC_out(PMINFO M1064_XPIXPLLCN, mnp >> 8); 154 matroxfb_DAC_out(minfo, M1064_XPIXPLLCN, mnp >> 8);
144 matroxfb_DAC_out(PMINFO M1064_XPIXPLLCP, mnp); 155 matroxfb_DAC_out(minfo, M1064_XPIXPLLCP, mnp);
145 return M1064_XPIXPLLSTAT; 156 return M1064_XPIXPLLSTAT;
146 157
147 case M_SYSTEM_PLL: 158 case M_SYSTEM_PLL:
148 matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLM, mnp >> 16); 159 matroxfb_DAC_out(minfo, DAC1064_XSYSPLLM, mnp >> 16);
149 matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLN, mnp >> 8); 160 matroxfb_DAC_out(minfo, DAC1064_XSYSPLLN, mnp >> 8);
150 matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLP, mnp); 161 matroxfb_DAC_out(minfo, DAC1064_XSYSPLLP, mnp);
151 return DAC1064_XSYSPLLSTAT; 162 return DAC1064_XSYSPLLSTAT;
152 163
153 case M_VIDEO_PLL: 164 case M_VIDEO_PLL:
154 matroxfb_DAC_out(PMINFO M1064_XVIDPLLM, mnp >> 16); 165 matroxfb_DAC_out(minfo, M1064_XVIDPLLM, mnp >> 16);
155 matroxfb_DAC_out(PMINFO M1064_XVIDPLLN, mnp >> 8); 166 matroxfb_DAC_out(minfo, M1064_XVIDPLLN, mnp >> 8);
156 matroxfb_DAC_out(PMINFO M1064_XVIDPLLP, mnp); 167 matroxfb_DAC_out(minfo, M1064_XVIDPLLP, mnp);
157 return M1064_XVIDPLLSTAT; 168 return M1064_XVIDPLLSTAT;
158 } 169 }
159 return 0; 170 return 0;
160} 171}
161 172
162static inline unsigned int g450_cmppll(CPMINFO unsigned int mnp, unsigned int pll) { 173static inline unsigned int g450_cmppll(const struct matrox_fb_info *minfo,
174 unsigned int mnp, unsigned int pll)
175{
163 unsigned char m = mnp >> 16; 176 unsigned char m = mnp >> 16;
164 unsigned char n = mnp >> 8; 177 unsigned char n = mnp >> 8;
165 unsigned char p = mnp; 178 unsigned char p = mnp;
166 179
167 switch (pll) { 180 switch (pll) {
168 case M_PIXEL_PLL_A: 181 case M_PIXEL_PLL_A:
169 return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLAM) != m || 182 return (matroxfb_DAC_in(minfo, M1064_XPIXPLLAM) != m ||
170 matroxfb_DAC_in(PMINFO M1064_XPIXPLLAN) != n || 183 matroxfb_DAC_in(minfo, M1064_XPIXPLLAN) != n ||
171 matroxfb_DAC_in(PMINFO M1064_XPIXPLLAP) != p); 184 matroxfb_DAC_in(minfo, M1064_XPIXPLLAP) != p);
172 185
173 case M_PIXEL_PLL_B: 186 case M_PIXEL_PLL_B:
174 return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLBM) != m || 187 return (matroxfb_DAC_in(minfo, M1064_XPIXPLLBM) != m ||
175 matroxfb_DAC_in(PMINFO M1064_XPIXPLLBN) != n || 188 matroxfb_DAC_in(minfo, M1064_XPIXPLLBN) != n ||
176 matroxfb_DAC_in(PMINFO M1064_XPIXPLLBP) != p); 189 matroxfb_DAC_in(minfo, M1064_XPIXPLLBP) != p);
177 190
178 case M_PIXEL_PLL_C: 191 case M_PIXEL_PLL_C:
179 return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) != m || 192 return (matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) != m ||
180 matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) != n || 193 matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) != n ||
181 matroxfb_DAC_in(PMINFO M1064_XPIXPLLCP) != p); 194 matroxfb_DAC_in(minfo, M1064_XPIXPLLCP) != p);
182 195
183 case M_SYSTEM_PLL: 196 case M_SYSTEM_PLL:
184 return (matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLM) != m || 197 return (matroxfb_DAC_in(minfo, DAC1064_XSYSPLLM) != m ||
185 matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLN) != n || 198 matroxfb_DAC_in(minfo, DAC1064_XSYSPLLN) != n ||
186 matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLP) != p); 199 matroxfb_DAC_in(minfo, DAC1064_XSYSPLLP) != p);
187 200
188 case M_VIDEO_PLL: 201 case M_VIDEO_PLL:
189 return (matroxfb_DAC_in(PMINFO M1064_XVIDPLLM) != m || 202 return (matroxfb_DAC_in(minfo, M1064_XVIDPLLM) != m ||
190 matroxfb_DAC_in(PMINFO M1064_XVIDPLLN) != n || 203 matroxfb_DAC_in(minfo, M1064_XVIDPLLN) != n ||
191 matroxfb_DAC_in(PMINFO M1064_XVIDPLLP) != p); 204 matroxfb_DAC_in(minfo, M1064_XVIDPLLP) != p);
192 } 205 }
193 return 1; 206 return 1;
194} 207}
195 208
196static inline int g450_isplllocked(CPMINFO unsigned int regidx) { 209static inline int g450_isplllocked(const struct matrox_fb_info *minfo,
210 unsigned int regidx)
211{
197 unsigned int j; 212 unsigned int j;
198 213
199 for (j = 0; j < 1000; j++) { 214 for (j = 0; j < 1000; j++) {
200 if (matroxfb_DAC_in(PMINFO regidx) & 0x40) { 215 if (matroxfb_DAC_in(minfo, regidx) & 0x40) {
201 unsigned int r = 0; 216 unsigned int r = 0;
202 int i; 217 int i;
203 218
204 for (i = 0; i < 100; i++) { 219 for (i = 0; i < 100; i++) {
205 r += matroxfb_DAC_in(PMINFO regidx) & 0x40; 220 r += matroxfb_DAC_in(minfo, regidx) & 0x40;
206 } 221 }
207 return r >= (90 * 0x40); 222 return r >= (90 * 0x40);
208 } 223 }
@@ -211,8 +226,10 @@ static inline int g450_isplllocked(CPMINFO unsigned int regidx) {
211 return 0; 226 return 0;
212} 227}
213 228
214static int g450_testpll(CPMINFO unsigned int mnp, unsigned int pll) { 229static int g450_testpll(const struct matrox_fb_info *minfo, unsigned int mnp,
215 return g450_isplllocked(PMINFO g450_setpll(PMINFO mnp, pll)); 230 unsigned int pll)
231{
232 return g450_isplllocked(minfo, g450_setpll(minfo, mnp, pll));
216} 233}
217 234
218static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) { 235static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) {
@@ -225,13 +242,19 @@ static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsi
225 } 242 }
226} 243}
227 244
228void matroxfb_g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll) { 245void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
229 if (g450_cmppll(PMINFO mnp, pll)) { 246 unsigned int pll)
230 g450_setpll(PMINFO mnp, pll); 247{
248 if (g450_cmppll(minfo, mnp, pll)) {
249 g450_setpll(minfo, mnp, pll);
231 } 250 }
232} 251}
233 252
234static inline unsigned int g450_findworkingpll(WPMINFO unsigned int pll, unsigned int* mnparray, unsigned int mnpcount) { 253static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo,
254 unsigned int pll,
255 unsigned int *mnparray,
256 unsigned int mnpcount)
257{
235 unsigned int found = 0; 258 unsigned int found = 0;
236 unsigned int idx; 259 unsigned int idx;
237 unsigned int mnpfound = mnparray[0]; 260 unsigned int mnpfound = mnparray[0];
@@ -255,22 +278,22 @@ static inline unsigned int g450_findworkingpll(WPMINFO unsigned int pll, unsigne
255 while (sptr >= sarray) { 278 while (sptr >= sarray) {
256 unsigned int mnp = *sptr--; 279 unsigned int mnp = *sptr--;
257 280
258 if (g450_testpll(PMINFO mnp - 0x0300, pll) && 281 if (g450_testpll(minfo, mnp - 0x0300, pll) &&
259 g450_testpll(PMINFO mnp + 0x0300, pll) && 282 g450_testpll(minfo, mnp + 0x0300, pll) &&
260 g450_testpll(PMINFO mnp - 0x0200, pll) && 283 g450_testpll(minfo, mnp - 0x0200, pll) &&
261 g450_testpll(PMINFO mnp + 0x0200, pll) && 284 g450_testpll(minfo, mnp + 0x0200, pll) &&
262 g450_testpll(PMINFO mnp - 0x0100, pll) && 285 g450_testpll(minfo, mnp - 0x0100, pll) &&
263 g450_testpll(PMINFO mnp + 0x0100, pll)) { 286 g450_testpll(minfo, mnp + 0x0100, pll)) {
264 if (g450_testpll(PMINFO mnp, pll)) { 287 if (g450_testpll(minfo, mnp, pll)) {
265 return mnp; 288 return mnp;
266 } 289 }
267 } else if (!found && g450_testpll(PMINFO mnp, pll)) { 290 } else if (!found && g450_testpll(minfo, mnp, pll)) {
268 mnpfound = mnp; 291 mnpfound = mnp;
269 found = 1; 292 found = 1;
270 } 293 }
271 } 294 }
272 } 295 }
273 g450_setpll(PMINFO mnpfound, pll); 296 g450_setpll(minfo, mnpfound, pll);
274 return mnpfound; 297 return mnpfound;
275} 298}
276 299
@@ -283,7 +306,9 @@ static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, uns
283 ci->data[0].mnp_value = mnp_value; 306 ci->data[0].mnp_value = mnp_value;
284} 307}
285 308
286static int g450_checkcache(WPMINFO struct matrox_pll_cache* ci, unsigned int mnp_key) { 309static int g450_checkcache(struct matrox_fb_info *minfo,
310 struct matrox_pll_cache *ci, unsigned int mnp_key)
311{
287 unsigned int i; 312 unsigned int i;
288 313
289 mnp_key &= G450_MNP_FREQBITS; 314 mnp_key &= G450_MNP_FREQBITS;
@@ -303,8 +328,10 @@ static int g450_checkcache(WPMINFO struct matrox_pll_cache* ci, unsigned int mnp
303 return NO_MORE_MNP; 328 return NO_MORE_MNP;
304} 329}
305 330
306static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, 331static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
307 unsigned int* mnparray, unsigned int* deltaarray) { 332 unsigned int pll, unsigned int *mnparray,
333 unsigned int *deltaarray)
334{
308 unsigned int mnpcount; 335 unsigned int mnpcount;
309 unsigned int pixel_vco; 336 unsigned int pixel_vco;
310 const struct matrox_pll_limits* pi; 337 const struct matrox_pll_limits* pi;
@@ -321,19 +348,19 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
321 348
322 matroxfb_DAC_lock_irqsave(flags); 349 matroxfb_DAC_lock_irqsave(flags);
323 350
324 xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); 351 xpwrctrl = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
325 matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN); 352 matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN);
326 mga_outb(M_SEQ_INDEX, M_SEQ1); 353 mga_outb(M_SEQ_INDEX, M_SEQ1);
327 mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF); 354 mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF);
328 tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL); 355 tmp = matroxfb_DAC_in(minfo, M1064_XPIXCLKCTRL);
329 tmp |= M1064_XPIXCLKCTRL_DIS; 356 tmp |= M1064_XPIXCLKCTRL_DIS;
330 if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) { 357 if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
331 tmp |= M1064_XPIXCLKCTRL_PLL_UP; 358 tmp |= M1064_XPIXCLKCTRL_PLL_UP;
332 } 359 }
333 matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); 360 matroxfb_DAC_out(minfo, M1064_XPIXCLKCTRL, tmp);
334 /* DVI PLL preferred for frequencies up to 361 /* DVI PLL preferred for frequencies up to
335 panel link max, standard PLL otherwise */ 362 panel link max, standard PLL otherwise */
336 if (fout >= MINFO->max_pixel_clock_panellink) 363 if (fout >= minfo->max_pixel_clock_panellink)
337 tmp = 0; 364 tmp = 0;
338 else tmp = 365 else tmp =
339 M1064_XDVICLKCTRL_DVIDATAPATHSEL | 366 M1064_XDVICLKCTRL_DVIDATAPATHSEL |
@@ -341,8 +368,8 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
341 M1064_XDVICLKCTRL_C1DVICLKEN | 368 M1064_XDVICLKCTRL_C1DVICLKEN |
342 M1064_XDVICLKCTRL_DVILOOPCTL | 369 M1064_XDVICLKCTRL_DVILOOPCTL |
343 M1064_XDVICLKCTRL_P1LOOPBWDTCTL; 370 M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
344 matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL,tmp); 371 matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp);
345 matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, 372 matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
346 xpwrctrl); 373 xpwrctrl);
347 374
348 matroxfb_DAC_unlock_irqrestore(flags); 375 matroxfb_DAC_unlock_irqrestore(flags);
@@ -363,20 +390,20 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
363 } 390 }
364 mga_outb(M_MISC_REG, misc); 391 mga_outb(M_MISC_REG, misc);
365 } 392 }
366 pi = &ACCESS_FBINFO(limits.pixel); 393 pi = &minfo->limits.pixel;
367 ci = &ACCESS_FBINFO(cache.pixel); 394 ci = &minfo->cache.pixel;
368 break; 395 break;
369 case M_SYSTEM_PLL: 396 case M_SYSTEM_PLL:
370 { 397 {
371 u_int32_t opt; 398 u_int32_t opt;
372 399
373 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &opt); 400 pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &opt);
374 if (!(opt & 0x20)) { 401 if (!(opt & 0x20)) {
375 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, opt | 0x20); 402 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, opt | 0x20);
376 } 403 }
377 } 404 }
378 pi = &ACCESS_FBINFO(limits.system); 405 pi = &minfo->limits.system;
379 ci = &ACCESS_FBINFO(cache.system); 406 ci = &minfo->cache.system;
380 break; 407 break;
381 case M_VIDEO_PLL: 408 case M_VIDEO_PLL:
382 { 409 {
@@ -385,18 +412,18 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
385 unsigned long flags; 412 unsigned long flags;
386 413
387 matroxfb_DAC_lock_irqsave(flags); 414 matroxfb_DAC_lock_irqsave(flags);
388 tmp = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); 415 tmp = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
389 if (!(tmp & 2)) { 416 if (!(tmp & 2)) {
390 matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, tmp | 2); 417 matroxfb_DAC_out(minfo, M1064_XPWRCTRL, tmp | 2);
391 } 418 }
392 419
393 mnp = matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) << 16; 420 mnp = matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) << 16;
394 mnp |= matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) << 8; 421 mnp |= matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) << 8;
395 pixel_vco = g450_mnp2vco(PMINFO mnp); 422 pixel_vco = g450_mnp2vco(minfo, mnp);
396 matroxfb_DAC_unlock_irqrestore(flags); 423 matroxfb_DAC_unlock_irqrestore(flags);
397 } 424 }
398 pi = &ACCESS_FBINFO(limits.video); 425 pi = &minfo->limits.video;
399 ci = &ACCESS_FBINFO(cache.video); 426 ci = &minfo->cache.video;
400 break; 427 break;
401 default: 428 default:
402 return -EINVAL; 429 return -EINVAL;
@@ -407,12 +434,12 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
407 unsigned int mnp; 434 unsigned int mnp;
408 unsigned int xvco; 435 unsigned int xvco;
409 436
410 for(mnp = g450_firstpll(PMINFO pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(PMINFO pi, &xvco, mnp)) { 437 for (mnp = g450_firstpll(minfo, pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(minfo, pi, &xvco, mnp)) {
411 unsigned int idx; 438 unsigned int idx;
412 unsigned int vco; 439 unsigned int vco;
413 unsigned int delta; 440 unsigned int delta;
414 441
415 vco = g450_mnp2vco(PMINFO mnp); 442 vco = g450_mnp2vco(minfo, mnp);
416#if 0 443#if 0
417 if (pll == M_VIDEO_PLL) { 444 if (pll == M_VIDEO_PLL) {
418 unsigned int big, small; 445 unsigned int big, small;
@@ -444,7 +471,7 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
444 * (freqs near VCOmin aren't as stable) 471 * (freqs near VCOmin aren't as stable)
445 */ 472 */
446 if (delta == deltaarray[idx-1] 473 if (delta == deltaarray[idx-1]
447 && vco != g450_mnp2vco(PMINFO mnparray[idx-1]) 474 && vco != g450_mnp2vco(minfo, mnparray[idx-1])
448 && vco < (pi->vcomin * 17 / 16)) { 475 && vco < (pi->vcomin * 17 / 16)) {
449 break; 476 break;
450 } 477 }
@@ -468,14 +495,14 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
468 unsigned int mnp; 495 unsigned int mnp;
469 496
470 matroxfb_DAC_lock_irqsave(flags); 497 matroxfb_DAC_lock_irqsave(flags);
471 mnp = g450_checkcache(PMINFO ci, mnparray[0]); 498 mnp = g450_checkcache(minfo, ci, mnparray[0]);
472 if (mnp != NO_MORE_MNP) { 499 if (mnp != NO_MORE_MNP) {
473 matroxfb_g450_setpll_cond(PMINFO mnp, pll); 500 matroxfb_g450_setpll_cond(minfo, mnp, pll);
474 } else { 501 } else {
475 mnp = g450_findworkingpll(PMINFO pll, mnparray, mnpcount); 502 mnp = g450_findworkingpll(minfo, pll, mnparray, mnpcount);
476 g450_addcache(ci, mnparray[0], mnp); 503 g450_addcache(ci, mnparray[0], mnp);
477 } 504 }
478 updatehwstate_clk(&ACCESS_FBINFO(hw), mnp, pll); 505 updatehwstate_clk(&minfo->hw, mnp, pll);
479 matroxfb_DAC_unlock_irqrestore(flags); 506 matroxfb_DAC_unlock_irqrestore(flags);
480 return mnp; 507 return mnp;
481 } 508 }
@@ -485,14 +512,16 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
485 * Currently there is 5(p) * 10(m) = 50 possible values. */ 512 * Currently there is 5(p) * 10(m) = 50 possible values. */
486#define MNP_TABLE_SIZE 64 513#define MNP_TABLE_SIZE 64
487 514
488int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll) { 515int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
516 unsigned int pll)
517{
489 unsigned int* arr; 518 unsigned int* arr;
490 519
491 arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL); 520 arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL);
492 if (arr) { 521 if (arr) {
493 int r; 522 int r;
494 523
495 r = __g450_setclk(PMINFO fout, pll, arr, arr + MNP_TABLE_SIZE); 524 r = __g450_setclk(minfo, fout, pll, arr, arr + MNP_TABLE_SIZE);
496 kfree(arr); 525 kfree(arr);
497 return r; 526 return r;
498 } 527 }
diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/matrox/g450_pll.h
index c17ed74501e9..aac615d18440 100644
--- a/drivers/video/matrox/g450_pll.h
+++ b/drivers/video/matrox/g450_pll.h
@@ -3,8 +3,10 @@
3 3
4#include "matroxfb_base.h" 4#include "matroxfb_base.h"
5 5
6int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll); 6int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
7unsigned int g450_mnp2f(CPMINFO unsigned int mnp); 7 unsigned int pll);
8void matroxfb_g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll); 8unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp);
9void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
10 unsigned int pll);
9 11
10#endif /* __G450_PLL_H__ */ 12#endif /* __G450_PLL_H__ */
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index c14e3e2212b3..f3728ab262f8 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -41,7 +41,7 @@ static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
41 int v; 41 int v;
42 42
43 matroxfb_DAC_lock_irqsave(flags); 43 matroxfb_DAC_lock_irqsave(flags);
44 v = matroxfb_DAC_in(PMINFO DAC_XGENIODATA); 44 v = matroxfb_DAC_in(minfo, DAC_XGENIODATA);
45 matroxfb_DAC_unlock_irqrestore(flags); 45 matroxfb_DAC_unlock_irqrestore(flags);
46 return v; 46 return v;
47} 47}
@@ -51,10 +51,10 @@ static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
51 int v; 51 int v;
52 52
53 matroxfb_DAC_lock_irqsave(flags); 53 matroxfb_DAC_lock_irqsave(flags);
54 v = (matroxfb_DAC_in(PMINFO DAC_XGENIOCTRL) & mask) | val; 54 v = (matroxfb_DAC_in(minfo, DAC_XGENIOCTRL) & mask) | val;
55 matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, v); 55 matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, v);
56 /* We must reset GENIODATA very often... XFree plays with this register */ 56 /* We must reset GENIODATA very often... XFree plays with this register */
57 matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0x00); 57 matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0x00);
58 matroxfb_DAC_unlock_irqrestore(flags); 58 matroxfb_DAC_unlock_irqrestore(flags);
59} 59}
60 60
@@ -112,7 +112,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
112 i2c_set_adapdata(&b->adapter, b); 112 i2c_set_adapdata(&b->adapter, b);
113 b->adapter.class = class; 113 b->adapter.class = class;
114 b->adapter.algo_data = &b->bac; 114 b->adapter.algo_data = &b->bac;
115 b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev; 115 b->adapter.dev.parent = &minfo->pcidev->dev;
116 b->bac = matrox_i2c_algo_template; 116 b->bac = matrox_i2c_algo_template;
117 b->bac.data = b; 117 b->bac.data = b;
118 err = i2c_bit_add_bus(&b->adapter); 118 err = i2c_bit_add_bus(&b->adapter);
@@ -149,11 +149,11 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
149 return NULL; 149 return NULL;
150 150
151 matroxfb_DAC_lock_irqsave(flags); 151 matroxfb_DAC_lock_irqsave(flags);
152 matroxfb_DAC_out(PMINFO DAC_XGENIODATA, 0xFF); 152 matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0xFF);
153 matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0x00); 153 matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, 0x00);
154 matroxfb_DAC_unlock_irqrestore(flags); 154 matroxfb_DAC_unlock_irqrestore(flags);
155 155
156 switch (ACCESS_FBINFO(chip)) { 156 switch (minfo->chip) {
157 case MGA_2064: 157 case MGA_2064:
158 case MGA_2164: 158 case MGA_2164:
159 err = i2c_bus_reg(&m2info->ddc1, minfo, 159 err = i2c_bus_reg(&m2info->ddc1, minfo,
@@ -168,7 +168,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
168 } 168 }
169 if (err) 169 if (err)
170 goto fail_ddc1; 170 goto fail_ddc1;
171 if (ACCESS_FBINFO(devflags.dualhead)) { 171 if (minfo->devflags.dualhead) {
172 err = i2c_bus_reg(&m2info->ddc2, minfo, 172 err = i2c_bus_reg(&m2info->ddc2, minfo,
173 DDC2_DATA, DDC2_CLK, 173 DDC2_DATA, DDC2_CLK,
174 "DDC:fb%u #1", I2C_CLASS_DDC); 174 "DDC:fb%u #1", I2C_CLASS_DDC);
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index 0ce3b0a89798..f9fa0fd00292 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -33,7 +33,11 @@
33#define DAC1064_OPT_MDIV2 0x00 33#define DAC1064_OPT_MDIV2 0x00
34#define DAC1064_OPT_RESERVED 0x10 34#define DAC1064_OPT_RESERVED 0x10
35 35
36static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post) { 36static void DAC1064_calcclock(const struct matrox_fb_info *minfo,
37 unsigned int freq, unsigned int fmax,
38 unsigned int *in, unsigned int *feed,
39 unsigned int *post)
40{
37 unsigned int fvco; 41 unsigned int fvco;
38 unsigned int p; 42 unsigned int p;
39 43
@@ -41,7 +45,7 @@ static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsi
41 45
42 /* only for devices older than G450 */ 46 /* only for devices older than G450 */
43 47
44 fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p); 48 fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
45 49
46 p = (1 << p) - 1; 50 p = (1 << p) - 1;
47 if (fvco <= 100000) 51 if (fvco <= 100000)
@@ -80,32 +84,35 @@ static const unsigned char MGA1064_DAC[] = {
80 0x00, 84 0x00,
81 0x00, 0x00, 0xFF, 0xFF}; 85 0x00, 0x00, 0xFF, 0xFF};
82 86
83static void DAC1064_setpclk(WPMINFO unsigned long fout) { 87static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
88{
84 unsigned int m, n, p; 89 unsigned int m, n, p;
85 90
86 DBG(__func__) 91 DBG(__func__)
87 92
88 DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); 93 DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
89 ACCESS_FBINFO(hw).DACclk[0] = m; 94 minfo->hw.DACclk[0] = m;
90 ACCESS_FBINFO(hw).DACclk[1] = n; 95 minfo->hw.DACclk[1] = n;
91 ACCESS_FBINFO(hw).DACclk[2] = p; 96 minfo->hw.DACclk[2] = p;
92} 97}
93 98
94static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { 99static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
100 unsigned long fmem)
101{
95 u_int32_t mx; 102 u_int32_t mx;
96 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 103 struct matrox_hw_state *hw = &minfo->hw;
97 104
98 DBG(__func__) 105 DBG(__func__)
99 106
100 if (ACCESS_FBINFO(devflags.noinit)) { 107 if (minfo->devflags.noinit) {
101 /* read MCLK and give up... */ 108 /* read MCLK and give up... */
102 hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); 109 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
103 hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); 110 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
104 hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); 111 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
105 return; 112 return;
106 } 113 }
107 mx = hw->MXoptionReg | 0x00000004; 114 mx = hw->MXoptionReg | 0x00000004;
108 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); 115 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
109 mx &= ~0x000000BB; 116 mx &= ~0x000000BB;
110 if (oscinfo & DAC1064_OPT_GDIV1) 117 if (oscinfo & DAC1064_OPT_GDIV1)
111 mx |= 0x00000008; 118 mx |= 0x00000008;
@@ -120,9 +127,9 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
120 127
121 /* powerup system PLL, select PCI clock */ 128 /* powerup system PLL, select PCI clock */
122 mx |= 0x00000020; 129 mx |= 0x00000020;
123 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); 130 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
124 mx &= ~0x00000004; 131 mx &= ~0x00000004;
125 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); 132 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
126 133
127 /* !!! you must not access device if MCLK is not running !!! 134 /* !!! you must not access device if MCLK is not running !!!
128 Doing so cause immediate PCI lockup :-( Maybe they should 135 Doing so cause immediate PCI lockup :-( Maybe they should
@@ -131,12 +138,12 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
131 perfect... */ 138 perfect... */
132 /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not 139 /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
133 select PLL... because of PLL can be stopped at this time) */ 140 select PLL... because of PLL can be stopped at this time) */
134 DAC1064_calcclock(PMINFO fmem, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); 141 DAC1064_calcclock(minfo, fmem, minfo->max_pixel_clock, &m, &n, &p);
135 outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3] = m); 142 outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3] = m);
136 outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4] = n); 143 outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4] = n);
137 outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5] = p); 144 outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5] = p);
138 for (clk = 65536; clk; --clk) { 145 for (clk = 65536; clk; --clk) {
139 if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT) & 0x40) 146 if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40)
140 break; 147 break;
141 } 148 }
142 if (!clk) 149 if (!clk)
@@ -147,29 +154,30 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
147 /* select specified system clock source */ 154 /* select specified system clock source */
148 mx |= oscinfo & DAC1064_OPT_SCLK_MASK; 155 mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
149 } 156 }
150 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); 157 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
151 mx &= ~0x00000004; 158 mx &= ~0x00000004;
152 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); 159 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
153 hw->MXoptionReg = mx; 160 hw->MXoptionReg = mx;
154} 161}
155 162
156#ifdef CONFIG_FB_MATROX_G 163#ifdef CONFIG_FB_MATROX_G
157static void g450_set_plls(WPMINFO2) { 164static void g450_set_plls(struct matrox_fb_info *minfo)
165{
158 u_int32_t c2_ctl; 166 u_int32_t c2_ctl;
159 unsigned int pxc; 167 unsigned int pxc;
160 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 168 struct matrox_hw_state *hw = &minfo->hw;
161 int pixelmnp; 169 int pixelmnp;
162 int videomnp; 170 int videomnp;
163 171
164 c2_ctl = hw->crtc2.ctl & ~0x4007; /* Clear PLL + enable for CRTC2 */ 172 c2_ctl = hw->crtc2.ctl & ~0x4007; /* Clear PLL + enable for CRTC2 */
165 c2_ctl |= 0x0001; /* Enable CRTC2 */ 173 c2_ctl |= 0x0001; /* Enable CRTC2 */
166 hw->DACreg[POS1064_XPWRCTRL] &= ~0x02; /* Stop VIDEO PLL */ 174 hw->DACreg[POS1064_XPWRCTRL] &= ~0x02; /* Stop VIDEO PLL */
167 pixelmnp = ACCESS_FBINFO(crtc1).mnp; 175 pixelmnp = minfo->crtc1.mnp;
168 videomnp = ACCESS_FBINFO(crtc2).mnp; 176 videomnp = minfo->crtc2.mnp;
169 if (videomnp < 0) { 177 if (videomnp < 0) {
170 c2_ctl &= ~0x0001; /* Disable CRTC2 */ 178 c2_ctl &= ~0x0001; /* Disable CRTC2 */
171 hw->DACreg[POS1064_XPWRCTRL] &= ~0x10; /* Powerdown CRTC2 */ 179 hw->DACreg[POS1064_XPWRCTRL] &= ~0x10; /* Powerdown CRTC2 */
172 } else if (ACCESS_FBINFO(crtc2).pixclock == ACCESS_FBINFO(features).pll.ref_freq) { 180 } else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) {
173 c2_ctl |= 0x4002; /* Use reference directly */ 181 c2_ctl |= 0x4002; /* Use reference directly */
174 } else if (videomnp == pixelmnp) { 182 } else if (videomnp == pixelmnp) {
175 c2_ctl |= 0x0004; /* Use pixel PLL */ 183 c2_ctl |= 0x0004; /* Use pixel PLL */
@@ -184,27 +192,27 @@ static void g450_set_plls(WPMINFO2) {
184 c2_ctl |= 0x0006; /* Use video PLL */ 192 c2_ctl |= 0x0006; /* Use video PLL */
185 hw->DACreg[POS1064_XPWRCTRL] |= 0x02; 193 hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
186 194
187 outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); 195 outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
188 matroxfb_g450_setpll_cond(PMINFO videomnp, M_VIDEO_PLL); 196 matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL);
189 } 197 }
190 198
191 hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP; 199 hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
192 if (pixelmnp >= 0) { 200 if (pixelmnp >= 0) {
193 hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP; 201 hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
194 202
195 outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); 203 outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
196 matroxfb_g450_setpll_cond(PMINFO pixelmnp, M_PIXEL_PLL_C); 204 matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C);
197 } 205 }
198 if (c2_ctl != hw->crtc2.ctl) { 206 if (c2_ctl != hw->crtc2.ctl) {
199 hw->crtc2.ctl = c2_ctl; 207 hw->crtc2.ctl = c2_ctl;
200 mga_outl(0x3C10, c2_ctl); 208 mga_outl(0x3C10, c2_ctl);
201 } 209 }
202 210
203 pxc = ACCESS_FBINFO(crtc1).pixclock; 211 pxc = minfo->crtc1.pixclock;
204 if (pxc == 0 || ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC2) { 212 if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) {
205 pxc = ACCESS_FBINFO(crtc2).pixclock; 213 pxc = minfo->crtc2.pixclock;
206 } 214 }
207 if (ACCESS_FBINFO(chip) == MGA_G550) { 215 if (minfo->chip == MGA_G550) {
208 if (pxc < 45000) { 216 if (pxc < 45000) {
209 hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-50 */ 217 hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-50 */
210 } else if (pxc < 55000) { 218 } else if (pxc < 55000) {
@@ -245,18 +253,19 @@ static void g450_set_plls(WPMINFO2) {
245} 253}
246#endif 254#endif
247 255
248void DAC1064_global_init(WPMINFO2) { 256void DAC1064_global_init(struct matrox_fb_info *minfo)
249 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 257{
258 struct matrox_hw_state *hw = &minfo->hw;
250 259
251 hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK; 260 hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
252 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN; 261 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
253 hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL; 262 hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
254#ifdef CONFIG_FB_MATROX_G 263#ifdef CONFIG_FB_MATROX_G
255 if (ACCESS_FBINFO(devflags.g450dac)) { 264 if (minfo->devflags.g450dac) {
256 hw->DACreg[POS1064_XPWRCTRL] = 0x1F; /* powerup everything */ 265 hw->DACreg[POS1064_XPWRCTRL] = 0x1F; /* powerup everything */
257 hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */ 266 hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */
258 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; 267 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
259 switch (ACCESS_FBINFO(outputs[0]).src) { 268 switch (minfo->outputs[0].src) {
260 case MATROXFB_SRC_CRTC1: 269 case MATROXFB_SRC_CRTC1:
261 case MATROXFB_SRC_CRTC2: 270 case MATROXFB_SRC_CRTC2:
262 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01; /* enable output; CRTC1/2 selection is in CRTC2 ctl */ 271 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01; /* enable output; CRTC1/2 selection is in CRTC2 ctl */
@@ -265,12 +274,12 @@ void DAC1064_global_init(WPMINFO2) {
265 hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN; 274 hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
266 break; 275 break;
267 } 276 }
268 switch (ACCESS_FBINFO(outputs[1]).src) { 277 switch (minfo->outputs[1].src) {
269 case MATROXFB_SRC_CRTC1: 278 case MATROXFB_SRC_CRTC1:
270 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04; 279 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
271 break; 280 break;
272 case MATROXFB_SRC_CRTC2: 281 case MATROXFB_SRC_CRTC2:
273 if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_MONITOR) { 282 if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) {
274 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08; 283 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
275 } else { 284 } else {
276 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C; 285 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
@@ -280,7 +289,7 @@ void DAC1064_global_init(WPMINFO2) {
280 hw->DACreg[POS1064_XPWRCTRL] &= ~0x01; /* Poweroff DAC2 */ 289 hw->DACreg[POS1064_XPWRCTRL] &= ~0x01; /* Poweroff DAC2 */
281 break; 290 break;
282 } 291 }
283 switch (ACCESS_FBINFO(outputs[2]).src) { 292 switch (minfo->outputs[2].src) {
284 case MATROXFB_SRC_CRTC1: 293 case MATROXFB_SRC_CRTC1:
285 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20; 294 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
286 break; 295 break;
@@ -299,55 +308,57 @@ void DAC1064_global_init(WPMINFO2) {
299 break; 308 break;
300 } 309 }
301 /* Now set timming related variables... */ 310 /* Now set timming related variables... */
302 g450_set_plls(PMINFO2); 311 g450_set_plls(minfo);
303 } else 312 } else
304#endif 313#endif
305 { 314 {
306 if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) { 315 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) {
307 hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT; 316 hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
308 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12; 317 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
309 } else if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { 318 } else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
310 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; 319 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
311 } else if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) 320 } else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1)
312 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12; 321 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
313 else 322 else
314 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS; 323 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
315 324
316 if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE) 325 if (minfo->outputs[0].src != MATROXFB_SRC_NONE)
317 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; 326 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
318 } 327 }
319} 328}
320 329
321void DAC1064_global_restore(WPMINFO2) { 330void DAC1064_global_restore(struct matrox_fb_info *minfo)
322 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 331{
323 332 struct matrox_hw_state *hw = &minfo->hw;
324 outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); 333
325 outDAC1064(PMINFO M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]); 334 outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
326 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { 335 outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
327 outDAC1064(PMINFO 0x20, 0x04); 336 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
328 outDAC1064(PMINFO 0x1F, ACCESS_FBINFO(devflags.dfp_type)); 337 outDAC1064(minfo, 0x20, 0x04);
329 if (ACCESS_FBINFO(devflags.g450dac)) { 338 outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type);
330 outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC); 339 if (minfo->devflags.g450dac) {
331 outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); 340 outDAC1064(minfo, M1064_XSYNCCTRL, 0xCC);
332 outDAC1064(PMINFO M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]); 341 outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
333 outDAC1064(PMINFO M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]); 342 outDAC1064(minfo, M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
343 outDAC1064(minfo, M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
334 } 344 }
335 } 345 }
336} 346}
337 347
338static int DAC1064_init_1(WPMINFO struct my_timming* m) { 348static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m)
339 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 349{
350 struct matrox_hw_state *hw = &minfo->hw;
340 351
341 DBG(__func__) 352 DBG(__func__)
342 353
343 memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs)); 354 memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
344 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { 355 switch (minfo->fbcon.var.bits_per_pixel) {
345 /* case 4: not supported by MGA1064 DAC */ 356 /* case 4: not supported by MGA1064 DAC */
346 case 8: 357 case 8:
347 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; 358 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
348 break; 359 break;
349 case 16: 360 case 16:
350 if (ACCESS_FBINFO(fbcon).var.green.length == 5) 361 if (minfo->fbcon.var.green.length == 5)
351 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; 362 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
352 else 363 else
353 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; 364 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
@@ -361,22 +372,23 @@ static int DAC1064_init_1(WPMINFO struct my_timming* m) {
361 default: 372 default:
362 return 1; /* unsupported depth */ 373 return 1; /* unsupported depth */
363 } 374 }
364 hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl); 375 hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl;
365 hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK; 376 hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
366 hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN; 377 hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
367 hw->DACreg[POS1064_XCURADDL] = 0; 378 hw->DACreg[POS1064_XCURADDL] = 0;
368 hw->DACreg[POS1064_XCURADDH] = 0; 379 hw->DACreg[POS1064_XCURADDH] = 0;
369 380
370 DAC1064_global_init(PMINFO2); 381 DAC1064_global_init(minfo);
371 return 0; 382 return 0;
372} 383}
373 384
374static int DAC1064_init_2(WPMINFO struct my_timming* m) { 385static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m)
375 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 386{
387 struct matrox_hw_state *hw = &minfo->hw;
376 388
377 DBG(__func__) 389 DBG(__func__)
378 390
379 if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 16) { /* 256 entries */ 391 if (minfo->fbcon.var.bits_per_pixel > 16) { /* 256 entries */
380 int i; 392 int i;
381 393
382 for (i = 0; i < 256; i++) { 394 for (i = 0; i < 256; i++) {
@@ -384,8 +396,8 @@ static int DAC1064_init_2(WPMINFO struct my_timming* m) {
384 hw->DACpal[i * 3 + 1] = i; 396 hw->DACpal[i * 3 + 1] = i;
385 hw->DACpal[i * 3 + 2] = i; 397 hw->DACpal[i * 3 + 2] = i;
386 } 398 }
387 } else if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 8) { 399 } else if (minfo->fbcon.var.bits_per_pixel > 8) {
388 if (ACCESS_FBINFO(fbcon).var.green.length == 5) { /* 0..31, 128..159 */ 400 if (minfo->fbcon.var.green.length == 5) { /* 0..31, 128..159 */
389 int i; 401 int i;
390 402
391 for (i = 0; i < 32; i++) { 403 for (i = 0; i < 32; i++) {
@@ -413,8 +425,9 @@ static int DAC1064_init_2(WPMINFO struct my_timming* m) {
413 return 0; 425 return 0;
414} 426}
415 427
416static void DAC1064_restore_1(WPMINFO2) { 428static void DAC1064_restore_1(struct matrox_fb_info *minfo)
417 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 429{
430 struct matrox_hw_state *hw = &minfo->hw;
418 431
419 CRITFLAGS 432 CRITFLAGS
420 433
@@ -422,28 +435,29 @@ static void DAC1064_restore_1(WPMINFO2) {
422 435
423 CRITBEGIN 436 CRITBEGIN
424 437
425 if ((inDAC1064(PMINFO DAC1064_XSYSPLLM) != hw->DACclk[3]) || 438 if ((inDAC1064(minfo, DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
426 (inDAC1064(PMINFO DAC1064_XSYSPLLN) != hw->DACclk[4]) || 439 (inDAC1064(minfo, DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
427 (inDAC1064(PMINFO DAC1064_XSYSPLLP) != hw->DACclk[5])) { 440 (inDAC1064(minfo, DAC1064_XSYSPLLP) != hw->DACclk[5])) {
428 outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]); 441 outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3]);
429 outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]); 442 outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4]);
430 outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]); 443 outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5]);
431 } 444 }
432 { 445 {
433 unsigned int i; 446 unsigned int i;
434 447
435 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { 448 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
436 if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL)) 449 if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
437 outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]); 450 outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]);
438 } 451 }
439 } 452 }
440 453
441 DAC1064_global_restore(PMINFO2); 454 DAC1064_global_restore(minfo);
442 455
443 CRITEND 456 CRITEND
444}; 457};
445 458
446static void DAC1064_restore_2(WPMINFO2) { 459static void DAC1064_restore_2(struct matrox_fb_info *minfo)
460{
447#ifdef DEBUG 461#ifdef DEBUG
448 unsigned int i; 462 unsigned int i;
449#endif 463#endif
@@ -453,12 +467,12 @@ static void DAC1064_restore_2(WPMINFO2) {
453#ifdef DEBUG 467#ifdef DEBUG
454 dprintk(KERN_DEBUG "DAC1064regs "); 468 dprintk(KERN_DEBUG "DAC1064regs ");
455 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { 469 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
456 dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); 470 dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]);
457 if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); 471 if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
458 } 472 }
459 dprintk("\n" KERN_DEBUG "DAC1064clk "); 473 dprintk(KERN_DEBUG "DAC1064clk ");
460 for (i = 0; i < 6; i++) 474 for (i = 0; i < 6; i++)
461 dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); 475 dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]);
462 dprintk("\n"); 476 dprintk("\n");
463#endif 477#endif
464} 478}
@@ -470,14 +484,14 @@ static int m1064_compute(void* out, struct my_timming* m) {
470 int tmout; 484 int tmout;
471 CRITFLAGS 485 CRITFLAGS
472 486
473 DAC1064_setpclk(PMINFO m->pixclock); 487 DAC1064_setpclk(minfo, m->pixclock);
474 488
475 CRITBEGIN 489 CRITBEGIN
476 490
477 for (i = 0; i < 3; i++) 491 for (i = 0; i < 3; i++)
478 outDAC1064(PMINFO M1064_XPIXPLLCM + i, ACCESS_FBINFO(hw).DACclk[i]); 492 outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]);
479 for (tmout = 500000; tmout; tmout--) { 493 for (tmout = 500000; tmout; tmout--) {
480 if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) 494 if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
481 break; 495 break;
482 udelay(10); 496 udelay(10);
483 }; 497 };
@@ -500,9 +514,9 @@ static struct matrox_altout m1064 = {
500static int g450_compute(void* out, struct my_timming* m) { 514static int g450_compute(void* out, struct my_timming* m) {
501#define minfo ((struct matrox_fb_info*)out) 515#define minfo ((struct matrox_fb_info*)out)
502 if (m->mnp < 0) { 516 if (m->mnp < 0) {
503 m->mnp = matroxfb_g450_setclk(PMINFO m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); 517 m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
504 if (m->mnp >= 0) { 518 if (m->mnp >= 0) {
505 m->pixclock = g450_mnp2f(PMINFO m->mnp); 519 m->pixclock = g450_mnp2f(minfo, m->mnp);
506 } 520 }
507 } 521 }
508#undef minfo 522#undef minfo
@@ -518,13 +532,14 @@ static struct matrox_altout g450out = {
518#endif /* NEED_DAC1064 */ 532#endif /* NEED_DAC1064 */
519 533
520#ifdef CONFIG_FB_MATROX_MYSTIQUE 534#ifdef CONFIG_FB_MATROX_MYSTIQUE
521static int MGA1064_init(WPMINFO struct my_timming* m) { 535static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m)
522 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 536{
537 struct matrox_hw_state *hw = &minfo->hw;
523 538
524 DBG(__func__) 539 DBG(__func__)
525 540
526 if (DAC1064_init_1(PMINFO m)) return 1; 541 if (DAC1064_init_1(minfo, m)) return 1;
527 if (matroxfb_vgaHWinit(PMINFO m)) return 1; 542 if (matroxfb_vgaHWinit(minfo, m)) return 1;
528 543
529 hw->MiscOutReg = 0xCB; 544 hw->MiscOutReg = 0xCB;
530 if (m->sync & FB_SYNC_HOR_HIGH_ACT) 545 if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -534,20 +549,21 @@ static int MGA1064_init(WPMINFO struct my_timming* m) {
534 if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ 549 if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
535 hw->CRTCEXT[3] |= 0x40; 550 hw->CRTCEXT[3] |= 0x40;
536 551
537 if (DAC1064_init_2(PMINFO m)) return 1; 552 if (DAC1064_init_2(minfo, m)) return 1;
538 return 0; 553 return 0;
539} 554}
540#endif 555#endif
541 556
542#ifdef CONFIG_FB_MATROX_G 557#ifdef CONFIG_FB_MATROX_G
543static int MGAG100_init(WPMINFO struct my_timming* m) { 558static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m)
544 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 559{
560 struct matrox_hw_state *hw = &minfo->hw;
545 561
546 DBG(__func__) 562 DBG(__func__)
547 563
548 if (DAC1064_init_1(PMINFO m)) return 1; 564 if (DAC1064_init_1(minfo, m)) return 1;
549 hw->MXoptionReg &= ~0x2000; 565 hw->MXoptionReg &= ~0x2000;
550 if (matroxfb_vgaHWinit(PMINFO m)) return 1; 566 if (matroxfb_vgaHWinit(minfo, m)) return 1;
551 567
552 hw->MiscOutReg = 0xEF; 568 hw->MiscOutReg = 0xEF;
553 if (m->sync & FB_SYNC_HOR_HIGH_ACT) 569 if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -557,27 +573,28 @@ static int MGAG100_init(WPMINFO struct my_timming* m) {
557 if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ 573 if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
558 hw->CRTCEXT[3] |= 0x40; 574 hw->CRTCEXT[3] |= 0x40;
559 575
560 if (DAC1064_init_2(PMINFO m)) return 1; 576 if (DAC1064_init_2(minfo, m)) return 1;
561 return 0; 577 return 0;
562} 578}
563#endif /* G */ 579#endif /* G */
564 580
565#ifdef CONFIG_FB_MATROX_MYSTIQUE 581#ifdef CONFIG_FB_MATROX_MYSTIQUE
566static void MGA1064_ramdac_init(WPMINFO2) { 582static void MGA1064_ramdac_init(struct matrox_fb_info *minfo)
583{
567 584
568 DBG(__func__) 585 DBG(__func__)
569 586
570 /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */ 587 /* minfo->features.DAC1064.vco_freq_min = 120000; */
571 ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; 588 minfo->features.pll.vco_freq_min = 62000;
572 ACCESS_FBINFO(features.pll.ref_freq) = 14318; 589 minfo->features.pll.ref_freq = 14318;
573 ACCESS_FBINFO(features.pll.feed_div_min) = 100; 590 minfo->features.pll.feed_div_min = 100;
574 ACCESS_FBINFO(features.pll.feed_div_max) = 127; 591 minfo->features.pll.feed_div_max = 127;
575 ACCESS_FBINFO(features.pll.in_div_min) = 1; 592 minfo->features.pll.in_div_min = 1;
576 ACCESS_FBINFO(features.pll.in_div_max) = 31; 593 minfo->features.pll.in_div_max = 31;
577 ACCESS_FBINFO(features.pll.post_shift_max) = 3; 594 minfo->features.pll.post_shift_max = 3;
578 ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL; 595 minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_EXTERNAL;
579 /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */ 596 /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
580 DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); 597 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
581} 598}
582#endif 599#endif
583 600
@@ -589,23 +606,25 @@ static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
589static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */ 606static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
590#endif 607#endif
591 608
592static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) { 609static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags,
610 int m, int n, int p)
611{
593 int reg; 612 int reg;
594 int selClk; 613 int selClk;
595 int clk; 614 int clk;
596 615
597 DBG(__func__) 616 DBG(__func__)
598 617
599 outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS | 618 outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
600 M1064_XPIXCLKCTRL_PLL_UP); 619 M1064_XPIXCLKCTRL_PLL_UP);
601 switch (flags & 3) { 620 switch (flags & 3) {
602 case 0: reg = M1064_XPIXPLLAM; break; 621 case 0: reg = M1064_XPIXPLLAM; break;
603 case 1: reg = M1064_XPIXPLLBM; break; 622 case 1: reg = M1064_XPIXPLLBM; break;
604 default: reg = M1064_XPIXPLLCM; break; 623 default: reg = M1064_XPIXPLLCM; break;
605 } 624 }
606 outDAC1064(PMINFO reg++, m); 625 outDAC1064(minfo, reg++, m);
607 outDAC1064(PMINFO reg++, n); 626 outDAC1064(minfo, reg++, n);
608 outDAC1064(PMINFO reg, p); 627 outDAC1064(minfo, reg, p);
609 selClk = mga_inb(M_MISC_REG_READ) & ~0xC; 628 selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
610 /* there should be flags & 0x03 & case 0/1/else */ 629 /* there should be flags & 0x03 & case 0/1/else */
611 /* and we should first select source and after that we should wait for PLL */ 630 /* and we should first select source and after that we should wait for PLL */
@@ -617,61 +636,64 @@ static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) {
617 } 636 }
618 mga_outb(M_MISC_REG, selClk); 637 mga_outb(M_MISC_REG, selClk);
619 for (clk = 500000; clk; clk--) { 638 for (clk = 500000; clk; clk--) {
620 if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) 639 if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
621 break; 640 break;
622 udelay(10); 641 udelay(10);
623 }; 642 };
624 if (!clk) 643 if (!clk)
625 printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A'); 644 printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
626 selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK; 645 selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
627 switch (flags & 0x0C) { 646 switch (flags & 0x0C) {
628 case 0x00: selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break; 647 case 0x00: selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
629 case 0x04: selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break; 648 case 0x04: selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
630 default: selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break; 649 default: selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
631 } 650 }
632 outDAC1064(PMINFO M1064_XPIXCLKCTRL, selClk); 651 outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk);
633 outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS); 652 outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
634} 653}
635 654
636static void MGAG100_setPixClock(CPMINFO int flags, int freq) { 655static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags,
656 int freq)
657{
637 unsigned int m, n, p; 658 unsigned int m, n, p;
638 659
639 DBG(__func__) 660 DBG(__func__)
640 661
641 DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); 662 DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p);
642 MGAG100_progPixClock(PMINFO flags, m, n, p); 663 MGAG100_progPixClock(minfo, flags, m, n, p);
643} 664}
644#endif 665#endif
645 666
646#ifdef CONFIG_FB_MATROX_MYSTIQUE 667#ifdef CONFIG_FB_MATROX_MYSTIQUE
647static int MGA1064_preinit(WPMINFO2) { 668static int MGA1064_preinit(struct matrox_fb_info *minfo)
669{
648 static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960, 670 static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960,
649 1024, 1152, 1280, 1600, 1664, 1920, 671 1024, 1152, 1280, 1600, 1664, 1920,
650 2048, 0}; 672 2048, 0};
651 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 673 struct matrox_hw_state *hw = &minfo->hw;
652 674
653 DBG(__func__) 675 DBG(__func__)
654 676
655 /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ 677 /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
656 ACCESS_FBINFO(capable.text) = 1; 678 minfo->capable.text = 1;
657 ACCESS_FBINFO(capable.vxres) = vxres_mystique; 679 minfo->capable.vxres = vxres_mystique;
658 680
659 ACCESS_FBINFO(outputs[0]).output = &m1064; 681 minfo->outputs[0].output = &m1064;
660 ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; 682 minfo->outputs[0].src = minfo->outputs[0].default_src;
661 ACCESS_FBINFO(outputs[0]).data = MINFO; 683 minfo->outputs[0].data = minfo;
662 ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 684 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
663 685
664 if (ACCESS_FBINFO(devflags.noinit)) 686 if (minfo->devflags.noinit)
665 return 0; /* do not modify settings */ 687 return 0; /* do not modify settings */
666 hw->MXoptionReg &= 0xC0000100; 688 hw->MXoptionReg &= 0xC0000100;
667 hw->MXoptionReg |= 0x00094E20; 689 hw->MXoptionReg |= 0x00094E20;
668 if (ACCESS_FBINFO(devflags.novga)) 690 if (minfo->devflags.novga)
669 hw->MXoptionReg &= ~0x00000100; 691 hw->MXoptionReg &= ~0x00000100;
670 if (ACCESS_FBINFO(devflags.nobios)) 692 if (minfo->devflags.nobios)
671 hw->MXoptionReg &= ~0x40000000; 693 hw->MXoptionReg &= ~0x40000000;
672 if (ACCESS_FBINFO(devflags.nopciretry)) 694 if (minfo->devflags.nopciretry)
673 hw->MXoptionReg |= 0x20000000; 695 hw->MXoptionReg |= 0x20000000;
674 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 696 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
675 mga_setr(M_SEQ_INDEX, 0x01, 0x20); 697 mga_setr(M_SEQ_INDEX, 0x01, 0x20);
676 mga_outl(M_CTLWTST, 0x00000000); 698 mga_outl(M_CTLWTST, 0x00000000);
677 udelay(200); 699 udelay(200);
@@ -681,101 +703,105 @@ static int MGA1064_preinit(WPMINFO2) {
681 return 0; 703 return 0;
682} 704}
683 705
684static void MGA1064_reset(WPMINFO2) { 706static void MGA1064_reset(struct matrox_fb_info *minfo)
707{
685 708
686 DBG(__func__); 709 DBG(__func__);
687 710
688 MGA1064_ramdac_init(PMINFO2); 711 MGA1064_ramdac_init(minfo);
689} 712}
690#endif 713#endif
691 714
692#ifdef CONFIG_FB_MATROX_G 715#ifdef CONFIG_FB_MATROX_G
693static void g450_mclk_init(WPMINFO2) { 716static void g450_mclk_init(struct matrox_fb_info *minfo)
717{
694 /* switch all clocks to PCI source */ 718 /* switch all clocks to PCI source */
695 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); 719 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
696 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3 & ~0x00300C03); 720 pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3 & ~0x00300C03);
697 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 721 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
698 722
699 if (((ACCESS_FBINFO(values).reg.opt3 & 0x000003) == 0x000003) || 723 if (((minfo->values.reg.opt3 & 0x000003) == 0x000003) ||
700 ((ACCESS_FBINFO(values).reg.opt3 & 0x000C00) == 0x000C00) || 724 ((minfo->values.reg.opt3 & 0x000C00) == 0x000C00) ||
701 ((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) { 725 ((minfo->values.reg.opt3 & 0x300000) == 0x300000)) {
702 matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL); 726 matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL);
703 } else { 727 } else {
704 unsigned long flags; 728 unsigned long flags;
705 unsigned int pwr; 729 unsigned int pwr;
706 730
707 matroxfb_DAC_lock_irqsave(flags); 731 matroxfb_DAC_lock_irqsave(flags);
708 pwr = inDAC1064(PMINFO M1064_XPWRCTRL) & ~0x02; 732 pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02;
709 outDAC1064(PMINFO M1064_XPWRCTRL, pwr); 733 outDAC1064(minfo, M1064_XPWRCTRL, pwr);
710 matroxfb_DAC_unlock_irqrestore(flags); 734 matroxfb_DAC_unlock_irqrestore(flags);
711 } 735 }
712 matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL); 736 matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL);
713 737
714 /* switch clocks to their real PLL source(s) */ 738 /* switch clocks to their real PLL source(s) */
715 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); 739 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
716 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3); 740 pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3);
717 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 741 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
718 742
719} 743}
720 744
721static void g450_memory_init(WPMINFO2) { 745static void g450_memory_init(struct matrox_fb_info *minfo)
746{
722 /* disable memory refresh */ 747 /* disable memory refresh */
723 ACCESS_FBINFO(hw).MXoptionReg &= ~0x001F8000; 748 minfo->hw.MXoptionReg &= ~0x001F8000;
724 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 749 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
725 750
726 /* set memory interface parameters */ 751 /* set memory interface parameters */
727 ACCESS_FBINFO(hw).MXoptionReg &= ~0x00207E00; 752 minfo->hw.MXoptionReg &= ~0x00207E00;
728 ACCESS_FBINFO(hw).MXoptionReg |= 0x00207E00 & ACCESS_FBINFO(values).reg.opt; 753 minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt;
729 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 754 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
730 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ACCESS_FBINFO(values).reg.opt2); 755 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2);
731 756
732 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); 757 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
733 758
734 /* first set up memory interface with disabled memory interface clocks */ 759 /* first set up memory interface with disabled memory interface clocks */
735 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc & ~0x80000000U); 760 pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U);
736 mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); 761 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
737 mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess); 762 mga_outl(M_MACCESS, minfo->values.reg.maccess);
738 /* start memory clocks */ 763 /* start memory clocks */
739 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc | 0x80000000U); 764 pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U);
740 765
741 udelay(200); 766 udelay(200);
742 767
743 if (ACCESS_FBINFO(values).memory.ddr && (!ACCESS_FBINFO(values).memory.emrswen || !ACCESS_FBINFO(values).memory.dll)) { 768 if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) {
744 mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk & ~0x1000); 769 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000);
745 } 770 }
746 mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000); 771 mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000);
747 772
748 udelay(200); 773 udelay(200);
749 774
750 ACCESS_FBINFO(hw).MXoptionReg |= 0x001F8000 & ACCESS_FBINFO(values).reg.opt; 775 minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt;
751 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 776 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
752 777
753 /* value is written to memory chips only if old != new */ 778 /* value is written to memory chips only if old != new */
754 mga_outl(M_PLNWT, 0); 779 mga_outl(M_PLNWT, 0);
755 mga_outl(M_PLNWT, ~0); 780 mga_outl(M_PLNWT, ~0);
756 781
757 if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) { 782 if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) {
758 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core); 783 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core);
759 } 784 }
760 785
761} 786}
762 787
763static void g450_preinit(WPMINFO2) { 788static void g450_preinit(struct matrox_fb_info *minfo)
789{
764 u_int32_t c2ctl; 790 u_int32_t c2ctl;
765 u_int8_t curctl; 791 u_int8_t curctl;
766 u_int8_t c1ctl; 792 u_int8_t c1ctl;
767 793
768 /* ACCESS_FBINFO(hw).MXoptionReg = minfo->values.reg.opt; */ 794 /* minfo->hw.MXoptionReg = minfo->values.reg.opt; */
769 ACCESS_FBINFO(hw).MXoptionReg &= 0xC0000100; 795 minfo->hw.MXoptionReg &= 0xC0000100;
770 ACCESS_FBINFO(hw).MXoptionReg |= 0x00000020; 796 minfo->hw.MXoptionReg |= 0x00000020;
771 if (ACCESS_FBINFO(devflags.novga)) 797 if (minfo->devflags.novga)
772 ACCESS_FBINFO(hw).MXoptionReg &= ~0x00000100; 798 minfo->hw.MXoptionReg &= ~0x00000100;
773 if (ACCESS_FBINFO(devflags.nobios)) 799 if (minfo->devflags.nobios)
774 ACCESS_FBINFO(hw).MXoptionReg &= ~0x40000000; 800 minfo->hw.MXoptionReg &= ~0x40000000;
775 if (ACCESS_FBINFO(devflags.nopciretry)) 801 if (minfo->devflags.nopciretry)
776 ACCESS_FBINFO(hw).MXoptionReg |= 0x20000000; 802 minfo->hw.MXoptionReg |= 0x20000000;
777 ACCESS_FBINFO(hw).MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x03400040; 803 minfo->hw.MXoptionReg |= minfo->values.reg.opt & 0x03400040;
778 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 804 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
779 805
780 /* Init system clocks */ 806 /* Init system clocks */
781 807
@@ -783,24 +809,24 @@ static void g450_preinit(WPMINFO2) {
783 c2ctl = mga_inl(M_C2CTL); 809 c2ctl = mga_inl(M_C2CTL);
784 mga_outl(M_C2CTL, c2ctl & ~1); 810 mga_outl(M_C2CTL, c2ctl & ~1);
785 /* stop cursor */ 811 /* stop cursor */
786 curctl = inDAC1064(PMINFO M1064_XCURCTRL); 812 curctl = inDAC1064(minfo, M1064_XCURCTRL);
787 outDAC1064(PMINFO M1064_XCURCTRL, 0); 813 outDAC1064(minfo, M1064_XCURCTRL, 0);
788 /* stop crtc1 */ 814 /* stop crtc1 */
789 c1ctl = mga_readr(M_SEQ_INDEX, 1); 815 c1ctl = mga_readr(M_SEQ_INDEX, 1);
790 mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20); 816 mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
791 817
792 g450_mclk_init(PMINFO2); 818 g450_mclk_init(minfo);
793 g450_memory_init(PMINFO2); 819 g450_memory_init(minfo);
794 820
795 /* set legacy VGA clock sources for DOSEmu or VMware... */ 821 /* set legacy VGA clock sources for DOSEmu or VMware... */
796 matroxfb_g450_setclk(PMINFO 25175, M_PIXEL_PLL_A); 822 matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A);
797 matroxfb_g450_setclk(PMINFO 28322, M_PIXEL_PLL_B); 823 matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B);
798 824
799 /* restore crtc1 */ 825 /* restore crtc1 */
800 mga_setr(M_SEQ_INDEX, 1, c1ctl); 826 mga_setr(M_SEQ_INDEX, 1, c1ctl);
801 827
802 /* restore cursor */ 828 /* restore cursor */
803 outDAC1064(PMINFO M1064_XCURCTRL, curctl); 829 outDAC1064(minfo, M1064_XCURCTRL, curctl);
804 830
805 /* restore crtc2 */ 831 /* restore crtc2 */
806 mga_outl(M_C2CTL, c2ctl); 832 mga_outl(M_C2CTL, c2ctl);
@@ -808,11 +834,12 @@ static void g450_preinit(WPMINFO2) {
808 return; 834 return;
809} 835}
810 836
811static int MGAG100_preinit(WPMINFO2) { 837static int MGAG100_preinit(struct matrox_fb_info *minfo)
838{
812 static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960, 839 static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960,
813 1024, 1152, 1280, 1600, 1664, 1920, 840 1024, 1152, 1280, 1600, 1664, 1920,
814 2048, 0}; 841 2048, 0};
815 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 842 struct matrox_hw_state *hw = &minfo->hw;
816 843
817 u_int32_t reg50; 844 u_int32_t reg50;
818#if 0 845#if 0
@@ -822,68 +849,68 @@ static int MGAG100_preinit(WPMINFO2) {
822 DBG(__func__) 849 DBG(__func__)
823 850
824 /* there are some instabilities if in_div > 19 && vco < 61000 */ 851 /* there are some instabilities if in_div > 19 && vco < 61000 */
825 if (ACCESS_FBINFO(devflags.g450dac)) { 852 if (minfo->devflags.g450dac) {
826 ACCESS_FBINFO(features.pll.vco_freq_min) = 130000; /* my sample: >118 */ 853 minfo->features.pll.vco_freq_min = 130000; /* my sample: >118 */
827 } else { 854 } else {
828 ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; 855 minfo->features.pll.vco_freq_min = 62000;
829 } 856 }
830 if (!ACCESS_FBINFO(features.pll.ref_freq)) { 857 if (!minfo->features.pll.ref_freq) {
831 ACCESS_FBINFO(features.pll.ref_freq) = 27000; 858 minfo->features.pll.ref_freq = 27000;
832 } 859 }
833 ACCESS_FBINFO(features.pll.feed_div_min) = 7; 860 minfo->features.pll.feed_div_min = 7;
834 ACCESS_FBINFO(features.pll.feed_div_max) = 127; 861 minfo->features.pll.feed_div_max = 127;
835 ACCESS_FBINFO(features.pll.in_div_min) = 1; 862 minfo->features.pll.in_div_min = 1;
836 ACCESS_FBINFO(features.pll.in_div_max) = 31; 863 minfo->features.pll.in_div_max = 31;
837 ACCESS_FBINFO(features.pll.post_shift_max) = 3; 864 minfo->features.pll.post_shift_max = 3;
838 ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT; 865 minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_G100_DEFAULT;
839 /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ 866 /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
840 ACCESS_FBINFO(capable.text) = 1; 867 minfo->capable.text = 1;
841 ACCESS_FBINFO(capable.vxres) = vxres_g100; 868 minfo->capable.vxres = vxres_g100;
842 ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 869 minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
843 ? ACCESS_FBINFO(devflags.sgram) : 1; 870 ? minfo->devflags.sgram : 1;
844 871
845#ifdef CONFIG_FB_MATROX_G 872#ifdef CONFIG_FB_MATROX_G
846 if (ACCESS_FBINFO(devflags.g450dac)) { 873 if (minfo->devflags.g450dac) {
847 ACCESS_FBINFO(outputs[0]).output = &g450out; 874 minfo->outputs[0].output = &g450out;
848 } else 875 } else
849#endif 876#endif
850 { 877 {
851 ACCESS_FBINFO(outputs[0]).output = &m1064; 878 minfo->outputs[0].output = &m1064;
852 } 879 }
853 ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; 880 minfo->outputs[0].src = minfo->outputs[0].default_src;
854 ACCESS_FBINFO(outputs[0]).data = MINFO; 881 minfo->outputs[0].data = minfo;
855 ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 882 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
856 883
857 if (ACCESS_FBINFO(devflags.g450dac)) { 884 if (minfo->devflags.g450dac) {
858 /* we must do this always, BIOS does not do it for us 885 /* we must do this always, BIOS does not do it for us
859 and accelerator dies without it */ 886 and accelerator dies without it */
860 mga_outl(0x1C0C, 0); 887 mga_outl(0x1C0C, 0);
861 } 888 }
862 if (ACCESS_FBINFO(devflags.noinit)) 889 if (minfo->devflags.noinit)
863 return 0; 890 return 0;
864 if (ACCESS_FBINFO(devflags.g450dac)) { 891 if (minfo->devflags.g450dac) {
865 g450_preinit(PMINFO2); 892 g450_preinit(minfo);
866 return 0; 893 return 0;
867 } 894 }
868 hw->MXoptionReg &= 0xC0000100; 895 hw->MXoptionReg &= 0xC0000100;
869 hw->MXoptionReg |= 0x00000020; 896 hw->MXoptionReg |= 0x00000020;
870 if (ACCESS_FBINFO(devflags.novga)) 897 if (minfo->devflags.novga)
871 hw->MXoptionReg &= ~0x00000100; 898 hw->MXoptionReg &= ~0x00000100;
872 if (ACCESS_FBINFO(devflags.nobios)) 899 if (minfo->devflags.nobios)
873 hw->MXoptionReg &= ~0x40000000; 900 hw->MXoptionReg &= ~0x40000000;
874 if (ACCESS_FBINFO(devflags.nopciretry)) 901 if (minfo->devflags.nopciretry)
875 hw->MXoptionReg |= 0x20000000; 902 hw->MXoptionReg |= 0x20000000;
876 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 903 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
877 DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333); 904 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
878 905
879 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) { 906 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
880 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50); 907 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
881 reg50 &= ~0x3000; 908 reg50 &= ~0x3000;
882 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); 909 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
883 910
884 hw->MXoptionReg |= 0x1080; 911 hw->MXoptionReg |= 0x1080;
885 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 912 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
886 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); 913 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
887 udelay(100); 914 udelay(100);
888 mga_outb(0x1C05, 0x00); 915 mga_outb(0x1C05, 0x00);
889 mga_outb(0x1C05, 0x80); 916 mga_outb(0x1C05, 0x80);
@@ -893,68 +920,69 @@ static int MGAG100_preinit(WPMINFO2) {
893 udelay(100); 920 udelay(100);
894 reg50 &= ~0xFF; 921 reg50 &= ~0xFF;
895 reg50 |= 0x07; 922 reg50 |= 0x07;
896 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); 923 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
897 /* it should help with G100 */ 924 /* it should help with G100 */
898 mga_outb(M_GRAPHICS_INDEX, 6); 925 mga_outb(M_GRAPHICS_INDEX, 6);
899 mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4); 926 mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
900 mga_setr(M_EXTVGA_INDEX, 0x03, 0x81); 927 mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
901 mga_setr(M_EXTVGA_INDEX, 0x04, 0x00); 928 mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
902 mga_writeb(ACCESS_FBINFO(video.vbase), 0x0000, 0xAA); 929 mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
903 mga_writeb(ACCESS_FBINFO(video.vbase), 0x0800, 0x55); 930 mga_writeb(minfo->video.vbase, 0x0800, 0x55);
904 mga_writeb(ACCESS_FBINFO(video.vbase), 0x4000, 0x55); 931 mga_writeb(minfo->video.vbase, 0x4000, 0x55);
905#if 0 932#if 0
906 if (mga_readb(ACCESS_FBINFO(video.vbase), 0x0000) != 0xAA) { 933 if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
907 hw->MXoptionReg &= ~0x1000; 934 hw->MXoptionReg &= ~0x1000;
908 } 935 }
909#endif 936#endif
910 hw->MXoptionReg |= 0x00078020; 937 hw->MXoptionReg |= 0x00078020;
911 } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) { 938 } else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
912 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50); 939 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
913 reg50 &= ~0x3000; 940 reg50 &= ~0x3000;
914 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); 941 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
915 942
916 if (ACCESS_FBINFO(devflags.memtype) == -1) 943 if (minfo->devflags.memtype == -1)
917 hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00; 944 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
918 else 945 else
919 hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; 946 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
920 if (ACCESS_FBINFO(devflags.sgram)) 947 if (minfo->devflags.sgram)
921 hw->MXoptionReg |= 0x4000; 948 hw->MXoptionReg |= 0x4000;
922 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); 949 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
923 mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); 950 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
924 udelay(200); 951 udelay(200);
925 mga_outl(M_MACCESS, 0x00000000); 952 mga_outl(M_MACCESS, 0x00000000);
926 mga_outl(M_MACCESS, 0x00008000); 953 mga_outl(M_MACCESS, 0x00008000);
927 udelay(100); 954 udelay(100);
928 mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); 955 mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
929 hw->MXoptionReg |= 0x00078020; 956 hw->MXoptionReg |= 0x00078020;
930 } else { 957 } else {
931 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50); 958 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
932 reg50 &= ~0x00000100; 959 reg50 &= ~0x00000100;
933 reg50 |= 0x00000000; 960 reg50 |= 0x00000000;
934 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); 961 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
935 962
936 if (ACCESS_FBINFO(devflags.memtype) == -1) 963 if (minfo->devflags.memtype == -1)
937 hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00; 964 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
938 else 965 else
939 hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; 966 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
940 if (ACCESS_FBINFO(devflags.sgram)) 967 if (minfo->devflags.sgram)
941 hw->MXoptionReg |= 0x4000; 968 hw->MXoptionReg |= 0x4000;
942 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); 969 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
943 mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); 970 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
944 udelay(200); 971 udelay(200);
945 mga_outl(M_MACCESS, 0x00000000); 972 mga_outl(M_MACCESS, 0x00000000);
946 mga_outl(M_MACCESS, 0x00008000); 973 mga_outl(M_MACCESS, 0x00008000);
947 udelay(100); 974 udelay(100);
948 mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); 975 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
949 hw->MXoptionReg |= 0x00040020; 976 hw->MXoptionReg |= 0x00040020;
950 } 977 }
951 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 978 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
952 return 0; 979 return 0;
953} 980}
954 981
955static void MGAG100_reset(WPMINFO2) { 982static void MGAG100_reset(struct matrox_fb_info *minfo)
983{
956 u_int8_t b; 984 u_int8_t b;
957 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 985 struct matrox_hw_state *hw = &minfo->hw;
958 986
959 DBG(__func__) 987 DBG(__func__)
960 988
@@ -964,54 +992,55 @@ static void MGAG100_reset(WPMINFO2) {
964 992
965 find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */ 993 find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
966 pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b); 994 pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
967 if (b == ACCESS_FBINFO(pcidev)->bus->number) { 995 if (b == minfo->pcidev->bus->number) {
968 pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */ 996 pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */
969 pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */ 997 pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */
970 pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */ 998 pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */
971 pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */ 999 pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */
972 } 1000 }
973#endif 1001#endif
974 if (!ACCESS_FBINFO(devflags.noinit)) { 1002 if (!minfo->devflags.noinit) {
975 if (x7AF4 & 8) { 1003 if (x7AF4 & 8) {
976 hw->MXoptionReg |= 0x40; /* FIXME... */ 1004 hw->MXoptionReg |= 0x40; /* FIXME... */
977 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 1005 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
978 } 1006 }
979 mga_setr(M_EXTVGA_INDEX, 0x06, 0x00); 1007 mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
980 } 1008 }
981 } 1009 }
982 if (ACCESS_FBINFO(devflags.g450dac)) { 1010 if (minfo->devflags.g450dac) {
983 /* either leave MCLK as is... or they were set in preinit */ 1011 /* either leave MCLK as is... or they were set in preinit */
984 hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); 1012 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
985 hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); 1013 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
986 hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); 1014 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
987 } else { 1015 } else {
988 DAC1064_setmclk(PMINFO DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333); 1016 DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
989 } 1017 }
990 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { 1018 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
991 if (ACCESS_FBINFO(devflags.dfp_type) == -1) { 1019 if (minfo->devflags.dfp_type == -1) {
992 ACCESS_FBINFO(devflags.dfp_type) = inDAC1064(PMINFO 0x1F); 1020 minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
993 } 1021 }
994 } 1022 }
995 if (ACCESS_FBINFO(devflags.noinit)) 1023 if (minfo->devflags.noinit)
996 return; 1024 return;
997 if (ACCESS_FBINFO(devflags.g450dac)) { 1025 if (minfo->devflags.g450dac) {
998 } else { 1026 } else {
999 MGAG100_setPixClock(PMINFO 4, 25175); 1027 MGAG100_setPixClock(minfo, 4, 25175);
1000 MGAG100_setPixClock(PMINFO 5, 28322); 1028 MGAG100_setPixClock(minfo, 5, 28322);
1001 if (x7AF4 & 0x10) { 1029 if (x7AF4 & 0x10) {
1002 b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1; 1030 b = inDAC1064(minfo, M1064_XGENIODATA) & ~1;
1003 outDAC1064(PMINFO M1064_XGENIODATA, b); 1031 outDAC1064(minfo, M1064_XGENIODATA, b);
1004 b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1; 1032 b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1;
1005 outDAC1064(PMINFO M1064_XGENIOCTRL, b); 1033 outDAC1064(minfo, M1064_XGENIOCTRL, b);
1006 } 1034 }
1007 } 1035 }
1008} 1036}
1009#endif 1037#endif
1010 1038
1011#ifdef CONFIG_FB_MATROX_MYSTIQUE 1039#ifdef CONFIG_FB_MATROX_MYSTIQUE
1012static void MGA1064_restore(WPMINFO2) { 1040static void MGA1064_restore(struct matrox_fb_info *minfo)
1041{
1013 int i; 1042 int i;
1014 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 1043 struct matrox_hw_state *hw = &minfo->hw;
1015 1044
1016 CRITFLAGS 1045 CRITFLAGS
1017 1046
@@ -1019,25 +1048,26 @@ static void MGA1064_restore(WPMINFO2) {
1019 1048
1020 CRITBEGIN 1049 CRITBEGIN
1021 1050
1022 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 1051 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1023 mga_outb(M_IEN, 0x00); 1052 mga_outb(M_IEN, 0x00);
1024 mga_outb(M_CACHEFLUSH, 0x00); 1053 mga_outb(M_CACHEFLUSH, 0x00);
1025 1054
1026 CRITEND 1055 CRITEND
1027 1056
1028 DAC1064_restore_1(PMINFO2); 1057 DAC1064_restore_1(minfo);
1029 matroxfb_vgaHWrestore(PMINFO2); 1058 matroxfb_vgaHWrestore(minfo);
1030 ACCESS_FBINFO(crtc1.panpos) = -1; 1059 minfo->crtc1.panpos = -1;
1031 for (i = 0; i < 6; i++) 1060 for (i = 0; i < 6; i++)
1032 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); 1061 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1033 DAC1064_restore_2(PMINFO2); 1062 DAC1064_restore_2(minfo);
1034} 1063}
1035#endif 1064#endif
1036 1065
1037#ifdef CONFIG_FB_MATROX_G 1066#ifdef CONFIG_FB_MATROX_G
1038static void MGAG100_restore(WPMINFO2) { 1067static void MGAG100_restore(struct matrox_fb_info *minfo)
1068{
1039 int i; 1069 int i;
1040 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 1070 struct matrox_hw_state *hw = &minfo->hw;
1041 1071
1042 CRITFLAGS 1072 CRITFLAGS
1043 1073
@@ -1045,19 +1075,17 @@ static void MGAG100_restore(WPMINFO2) {
1045 1075
1046 CRITBEGIN 1076 CRITBEGIN
1047 1077
1048 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 1078 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1049 CRITEND 1079 CRITEND
1050 1080
1051 DAC1064_restore_1(PMINFO2); 1081 DAC1064_restore_1(minfo);
1052 matroxfb_vgaHWrestore(PMINFO2); 1082 matroxfb_vgaHWrestore(minfo);
1053#ifdef CONFIG_FB_MATROX_32MB 1083 if (minfo->devflags.support32MB)
1054 if (ACCESS_FBINFO(devflags.support32MB))
1055 mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]); 1084 mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
1056#endif 1085 minfo->crtc1.panpos = -1;
1057 ACCESS_FBINFO(crtc1.panpos) = -1;
1058 for (i = 0; i < 6; i++) 1086 for (i = 0; i < 6; i++)
1059 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); 1087 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1060 DAC1064_restore_2(PMINFO2); 1088 DAC1064_restore_2(minfo);
1061} 1089}
1062#endif 1090#endif
1063 1091
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
index 7a98ce8043d7..c6ed7801efe2 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/matrox/matroxfb_DAC1064.h
@@ -11,8 +11,8 @@ extern struct matrox_switch matrox_mystique;
11extern struct matrox_switch matrox_G100; 11extern struct matrox_switch matrox_G100;
12#endif 12#endif
13#ifdef NEED_DAC1064 13#ifdef NEED_DAC1064
14void DAC1064_global_init(WPMINFO2); 14void DAC1064_global_init(struct matrox_fb_info *minfo);
15void DAC1064_global_restore(WPMINFO2); 15void DAC1064_global_restore(struct matrox_fb_info *minfo);
16#endif 16#endif
17 17
18#define M1064_INDEX 0x00 18#define M1064_INDEX 0x00
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
index 13524821e242..835aaaae6b96 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ b/drivers/video/matrox/matroxfb_Ti3026.c
@@ -279,27 +279,31 @@ static const unsigned char MGADACbpp32[] =
279 TVP3026_XCOLKEYCTRL_ZOOM1, 279 TVP3026_XCOLKEYCTRL_ZOOM1,
280 0x00, 0x00, TVP3026_XCURCTRL_DIS }; 280 0x00, 0x00, TVP3026_XCURCTRL_DIS };
281 281
282static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* in, int* feed, int* post) { 282static int Ti3026_calcclock(const struct matrox_fb_info *minfo,
283 unsigned int freq, unsigned int fmax, int *in,
284 int *feed, int *post)
285{
283 unsigned int fvco; 286 unsigned int fvco;
284 unsigned int lin, lfeed, lpost; 287 unsigned int lin, lfeed, lpost;
285 288
286 DBG(__func__) 289 DBG(__func__)
287 290
288 fvco = PLL_calcclock(PMINFO freq, fmax, &lin, &lfeed, &lpost); 291 fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost);
289 fvco >>= (*post = lpost); 292 fvco >>= (*post = lpost);
290 *in = 64 - lin; 293 *in = 64 - lin;
291 *feed = 64 - lfeed; 294 *feed = 64 - lfeed;
292 return fvco; 295 return fvco;
293} 296}
294 297
295static int Ti3026_setpclk(WPMINFO int clk) { 298static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk)
299{
296 unsigned int f_pll; 300 unsigned int f_pll;
297 unsigned int pixfeed, pixin, pixpost; 301 unsigned int pixfeed, pixin, pixpost;
298 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 302 struct matrox_hw_state *hw = &minfo->hw;
299 303
300 DBG(__func__) 304 DBG(__func__)
301 305
302 f_pll = Ti3026_calcclock(PMINFO clk, ACCESS_FBINFO(max_pixel_clock), &pixin, &pixfeed, &pixpost); 306 f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost);
303 307
304 hw->DACclk[0] = pixin | 0xC0; 308 hw->DACclk[0] = pixin | 0xC0;
305 hw->DACclk[1] = pixfeed; 309 hw->DACclk[1] = pixfeed;
@@ -309,9 +313,9 @@ static int Ti3026_setpclk(WPMINFO int clk) {
309 unsigned int loopfeed, loopin, looppost, loopdiv, z; 313 unsigned int loopfeed, loopin, looppost, loopdiv, z;
310 unsigned int Bpp; 314 unsigned int Bpp;
311 315
312 Bpp = ACCESS_FBINFO(curr.final_bppShift); 316 Bpp = minfo->curr.final_bppShift;
313 317
314 if (ACCESS_FBINFO(fbcon).var.bits_per_pixel == 24) { 318 if (minfo->fbcon.var.bits_per_pixel == 24) {
315 loopfeed = 3; /* set lm to any possible value */ 319 loopfeed = 3; /* set lm to any possible value */
316 loopin = 3 * 32 / Bpp; 320 loopin = 3 * 32 / Bpp;
317 } else { 321 } else {
@@ -330,18 +334,18 @@ static int Ti3026_setpclk(WPMINFO int clk) {
330 looppost = 3; 334 looppost = 3;
331 loopdiv = z/16; 335 loopdiv = z/16;
332 } 336 }
333 if (ACCESS_FBINFO(fbcon).var.bits_per_pixel == 24) { 337 if (minfo->fbcon.var.bits_per_pixel == 24) {
334 hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; 338 hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
335 hw->DACclk[4] = (65 - loopfeed) | 0x80; 339 hw->DACclk[4] = (65 - loopfeed) | 0x80;
336 if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) { 340 if (minfo->accel.ramdac_rev > 0x20) {
337 if (isInterleave(MINFO)) 341 if (isInterleave(minfo))
338 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3; 342 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
339 else { 343 else {
340 hw->DACclk[4] &= ~0xC0; 344 hw->DACclk[4] &= ~0xC0;
341 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3; 345 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
342 } 346 }
343 } else { 347 } else {
344 if (isInterleave(MINFO)) 348 if (isInterleave(minfo))
345 ; /* default... */ 349 ; /* default... */
346 else { 350 else {
347 hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */ 351 hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */
@@ -349,7 +353,7 @@ static int Ti3026_setpclk(WPMINFO int clk) {
349 } 353 }
350 } 354 }
351 hw->DACclk[5] = looppost | 0xF8; 355 hw->DACclk[5] = looppost | 0xF8;
352 if (ACCESS_FBINFO(devflags.mga_24bpp_fix)) 356 if (minfo->devflags.mga_24bpp_fix)
353 hw->DACclk[5] ^= 0x40; 357 hw->DACclk[5] ^= 0x40;
354 } else { 358 } else {
355 hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0; 359 hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
@@ -361,14 +365,15 @@ static int Ti3026_setpclk(WPMINFO int clk) {
361 return 0; 365 return 0;
362} 366}
363 367
364static int Ti3026_init(WPMINFO struct my_timming* m) { 368static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
365 u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT; 369{
366 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 370 u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
371 struct matrox_hw_state *hw = &minfo->hw;
367 372
368 DBG(__func__) 373 DBG(__func__)
369 374
370 memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg)); 375 memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
371 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { 376 switch (minfo->fbcon.var.bits_per_pixel) {
372 case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */ 377 case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
373 hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; 378 hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
374 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT; 379 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
@@ -383,7 +388,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m) {
383 break; 388 break;
384 case 16: 389 case 16:
385 /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */ 390 /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */
386 hw->DACreg[POS3026_XTRUECOLORCTRL] = (ACCESS_FBINFO(fbcon).var.green.length == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565); 391 hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
387 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT; 392 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
388 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2; 393 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
389 break; 394 break;
@@ -400,7 +405,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m) {
400 default: 405 default:
401 return 1; /* TODO: failed */ 406 return 1; /* TODO: failed */
402 } 407 }
403 if (matroxfb_vgaHWinit(PMINFO m)) return 1; 408 if (matroxfb_vgaHWinit(minfo, m)) return 1;
404 409
405 /* set SYNC */ 410 /* set SYNC */
406 hw->MiscOutReg = 0xCB; 411 hw->MiscOutReg = 0xCB;
@@ -412,9 +417,9 @@ static int Ti3026_init(WPMINFO struct my_timming* m) {
412 hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN; 417 hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
413 418
414 /* set DELAY */ 419 /* set DELAY */
415 if (ACCESS_FBINFO(video.len) < 0x400000) 420 if (minfo->video.len < 0x400000)
416 hw->CRTCEXT[3] |= 0x08; 421 hw->CRTCEXT[3] |= 0x08;
417 else if (ACCESS_FBINFO(video.len) > 0x400000) 422 else if (minfo->video.len > 0x400000)
418 hw->CRTCEXT[3] |= 0x10; 423 hw->CRTCEXT[3] |= 0x10;
419 424
420 /* set HWCURSOR */ 425 /* set HWCURSOR */
@@ -426,14 +431,15 @@ static int Ti3026_init(WPMINFO struct my_timming* m) {
426 431
427 /* set interleaving */ 432 /* set interleaving */
428 hw->MXoptionReg &= ~0x00001000; 433 hw->MXoptionReg &= ~0x00001000;
429 if (isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000; 434 if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000;
430 435
431 /* set DAC */ 436 /* set DAC */
432 Ti3026_setpclk(PMINFO m->pixclock); 437 Ti3026_setpclk(minfo, m->pixclock);
433 return 0; 438 return 0;
434} 439}
435 440
436static void ti3026_setMCLK(WPMINFO int fout){ 441static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
442{
437 unsigned int f_pll; 443 unsigned int f_pll;
438 unsigned int pclk_m, pclk_n, pclk_p; 444 unsigned int pclk_m, pclk_n, pclk_p;
439 unsigned int mclk_m, mclk_n, mclk_p; 445 unsigned int mclk_m, mclk_n, mclk_p;
@@ -442,29 +448,29 @@ static void ti3026_setMCLK(WPMINFO int fout){
442 448
443 DBG(__func__) 449 DBG(__func__)
444 450
445 f_pll = Ti3026_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &mclk_n, &mclk_m, &mclk_p); 451 f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);
446 452
447 /* save pclk */ 453 /* save pclk */
448 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC); 454 outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
449 pclk_n = inTi3026(PMINFO TVP3026_XPIXPLLDATA); 455 pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
450 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFD); 456 outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
451 pclk_m = inTi3026(PMINFO TVP3026_XPIXPLLDATA); 457 pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
452 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE); 458 outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
453 pclk_p = inTi3026(PMINFO TVP3026_XPIXPLLDATA); 459 pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);
454 460
455 /* stop pclk */ 461 /* stop pclk */
456 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE); 462 outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
457 outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00); 463 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
458 464
459 /* set pclk to new mclk */ 465 /* set pclk to new mclk */
460 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC); 466 outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
461 outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_n | 0xC0); 467 outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
462 outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_m); 468 outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
463 outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_p | 0xB0); 469 outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
464 470
465 /* wait for PLL to lock */ 471 /* wait for PLL to lock */
466 for (tmout = 500000; tmout; tmout--) { 472 for (tmout = 500000; tmout; tmout--) {
467 if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40) 473 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
468 break; 474 break;
469 udelay(10); 475 udelay(10);
470 }; 476 };
@@ -472,23 +478,23 @@ static void ti3026_setMCLK(WPMINFO int fout){
472 printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n"); 478 printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
473 479
474 /* output pclk on mclk pin */ 480 /* output pclk on mclk pin */
475 mclk_ctl = inTi3026(PMINFO TVP3026_XMEMPLLCTRL); 481 mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
476 outTi3026(PMINFO TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7); 482 outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
477 outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4); 483 outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
478 484
479 /* stop MCLK */ 485 /* stop MCLK */
480 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFB); 486 outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
481 outTi3026(PMINFO TVP3026_XMEMPLLDATA, 0x00); 487 outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);
482 488
483 /* set mclk to new freq */ 489 /* set mclk to new freq */
484 outTi3026(PMINFO TVP3026_XPLLADDR, 0xF3); 490 outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
485 outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_n | 0xC0); 491 outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
486 outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_m); 492 outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
487 outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_p | 0xB0); 493 outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
488 494
489 /* wait for PLL to lock */ 495 /* wait for PLL to lock */
490 for (tmout = 500000; tmout; tmout--) { 496 for (tmout = 500000; tmout; tmout--) {
491 if (inTi3026(PMINFO TVP3026_XMEMPLLDATA) & 0x40) 497 if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
492 break; 498 break;
493 udelay(10); 499 udelay(10);
494 } 500 }
@@ -496,7 +502,7 @@ static void ti3026_setMCLK(WPMINFO int fout){
496 printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n"); 502 printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
497 503
498 f_pll = f_pll * 333 / (10000 << mclk_p); 504 f_pll = f_pll * 333 / (10000 << mclk_p);
499 if (isMilleniumII(MINFO)) { 505 if (isMilleniumII(minfo)) {
500 rfhcnt = (f_pll - 128) / 256; 506 rfhcnt = (f_pll - 128) / 256;
501 if (rfhcnt > 15) 507 if (rfhcnt > 15)
502 rfhcnt = 15; 508 rfhcnt = 15;
@@ -505,26 +511,26 @@ static void ti3026_setMCLK(WPMINFO int fout){
505 if (rfhcnt > 15) 511 if (rfhcnt > 15)
506 rfhcnt = 0; 512 rfhcnt = 0;
507 } 513 }
508 ACCESS_FBINFO(hw).MXoptionReg = (ACCESS_FBINFO(hw).MXoptionReg & ~0x000F0000) | (rfhcnt << 16); 514 minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
509 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); 515 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
510 516
511 /* output MCLK to MCLK pin */ 517 /* output MCLK to MCLK pin */
512 outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); 518 outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
513 outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4); 519 outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
514 520
515 /* stop PCLK */ 521 /* stop PCLK */
516 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE); 522 outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
517 outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00); 523 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
518 524
519 /* restore pclk */ 525 /* restore pclk */
520 outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC); 526 outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
521 outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_n); 527 outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
522 outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_m); 528 outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
523 outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_p); 529 outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);
524 530
525 /* wait for PLL to lock */ 531 /* wait for PLL to lock */
526 for (tmout = 500000; tmout; tmout--) { 532 for (tmout = 500000; tmout; tmout--) {
527 if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40) 533 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
528 break; 534 break;
529 udelay(10); 535 udelay(10);
530 } 536 }
@@ -532,26 +538,27 @@ static void ti3026_setMCLK(WPMINFO int fout){
532 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); 538 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
533} 539}
534 540
535static void ti3026_ramdac_init(WPMINFO2) { 541static void ti3026_ramdac_init(struct matrox_fb_info *minfo)
536 542{
537 DBG(__func__) 543 DBG(__func__)
538 544
539 ACCESS_FBINFO(features.pll.vco_freq_min) = 110000; 545 minfo->features.pll.vco_freq_min = 110000;
540 ACCESS_FBINFO(features.pll.ref_freq) = 114545; 546 minfo->features.pll.ref_freq = 114545;
541 ACCESS_FBINFO(features.pll.feed_div_min) = 2; 547 minfo->features.pll.feed_div_min = 2;
542 ACCESS_FBINFO(features.pll.feed_div_max) = 24; 548 minfo->features.pll.feed_div_max = 24;
543 ACCESS_FBINFO(features.pll.in_div_min) = 2; 549 minfo->features.pll.in_div_min = 2;
544 ACCESS_FBINFO(features.pll.in_div_max) = 63; 550 minfo->features.pll.in_div_max = 63;
545 ACCESS_FBINFO(features.pll.post_shift_max) = 3; 551 minfo->features.pll.post_shift_max = 3;
546 if (ACCESS_FBINFO(devflags.noinit)) 552 if (minfo->devflags.noinit)
547 return; 553 return;
548 ti3026_setMCLK(PMINFO 60000); 554 ti3026_setMCLK(minfo, 60000);
549} 555}
550 556
551static void Ti3026_restore(WPMINFO2) { 557static void Ti3026_restore(struct matrox_fb_info *minfo)
558{
552 int i; 559 int i;
553 unsigned char progdac[6]; 560 unsigned char progdac[6];
554 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 561 struct matrox_hw_state *hw = &minfo->hw;
555 CRITFLAGS 562 CRITFLAGS
556 563
557 DBG(__func__) 564 DBG(__func__)
@@ -565,31 +572,31 @@ static void Ti3026_restore(WPMINFO2) {
565 572
566 CRITBEGIN 573 CRITBEGIN
567 574
568 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 575 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
569 576
570 CRITEND 577 CRITEND
571 578
572 matroxfb_vgaHWrestore(PMINFO2); 579 matroxfb_vgaHWrestore(minfo);
573 580
574 CRITBEGIN 581 CRITBEGIN
575 582
576 ACCESS_FBINFO(crtc1.panpos) = -1; 583 minfo->crtc1.panpos = -1;
577 for (i = 0; i < 6; i++) 584 for (i = 0; i < 6; i++)
578 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); 585 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
579 586
580 for (i = 0; i < 21; i++) { 587 for (i = 0; i < 21; i++) {
581 outTi3026(PMINFO DACseq[i], hw->DACreg[i]); 588 outTi3026(minfo, DACseq[i], hw->DACreg[i]);
582 } 589 }
583 590
584 outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); 591 outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
585 progdac[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); 592 progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
586 progdac[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); 593 progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
587 outTi3026(PMINFO TVP3026_XPLLADDR, 0x15); 594 outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
588 progdac[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); 595 progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
589 progdac[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); 596 progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
590 outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); 597 outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
591 progdac[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); 598 progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
592 progdac[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); 599 progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
593 600
594 CRITEND 601 CRITEND
595 if (memcmp(hw->DACclk, progdac, 6)) { 602 if (memcmp(hw->DACclk, progdac, 6)) {
@@ -598,20 +605,20 @@ static void Ti3026_restore(WPMINFO2) {
598 /* Maybe even we should call schedule() ? */ 605 /* Maybe even we should call schedule() ? */
599 606
600 CRITBEGIN 607 CRITBEGIN
601 outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]); 608 outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
602 outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); 609 outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
603 outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0); 610 outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
604 outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0); 611 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);
605 612
606 outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); 613 outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
607 for (i = 0; i < 3; i++) 614 for (i = 0; i < 3; i++)
608 outTi3026(PMINFO TVP3026_XPIXPLLDATA, hw->DACclk[i]); 615 outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
609 /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */ 616 /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
610 if (hw->MiscOutReg & 0x08) { 617 if (hw->MiscOutReg & 0x08) {
611 int tmout; 618 int tmout;
612 outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F); 619 outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
613 for (tmout = 500000; tmout; --tmout) { 620 for (tmout = 500000; tmout; --tmout) {
614 if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40) 621 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
615 break; 622 break;
616 udelay(10); 623 udelay(10);
617 } 624 }
@@ -624,18 +631,18 @@ static void Ti3026_restore(WPMINFO2) {
624 dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout); 631 dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
625 CRITBEGIN 632 CRITBEGIN
626 } 633 }
627 outTi3026(PMINFO TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]); 634 outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
628 outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); 635 outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
629 for (i = 3; i < 6; i++) 636 for (i = 3; i < 6; i++)
630 outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]); 637 outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
631 CRITEND 638 CRITEND
632 if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) { 639 if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
633 int tmout; 640 int tmout;
634 641
635 CRITBEGIN 642 CRITBEGIN
636 outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F); 643 outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
637 for (tmout = 500000; tmout; --tmout) { 644 for (tmout = 500000; tmout; --tmout) {
638 if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA) & 0x40) 645 if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40)
639 break; 646 break;
640 udelay(10); 647 udelay(10);
641 } 648 }
@@ -651,74 +658,75 @@ static void Ti3026_restore(WPMINFO2) {
651 dprintk(KERN_DEBUG "3026DACregs "); 658 dprintk(KERN_DEBUG "3026DACregs ");
652 for (i = 0; i < 21; i++) { 659 for (i = 0; i < 21; i++) {
653 dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]); 660 dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
654 if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); 661 if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
655 } 662 }
656 dprintk("\n" KERN_DEBUG "DACclk "); 663 dprintk(KERN_DEBUG "DACclk ");
657 for (i = 0; i < 6; i++) 664 for (i = 0; i < 6; i++)
658 dprintk("C%02X=%02X ", i, hw->DACclk[i]); 665 dprintk("C%02X=%02X ", i, hw->DACclk[i]);
659 dprintk("\n"); 666 dprintk("\n");
660#endif 667#endif
661} 668}
662 669
663static void Ti3026_reset(WPMINFO2) { 670static void Ti3026_reset(struct matrox_fb_info *minfo)
664 671{
665 DBG(__func__) 672 DBG(__func__)
666 673
667 ti3026_ramdac_init(PMINFO2); 674 ti3026_ramdac_init(minfo);
668} 675}
669 676
670static struct matrox_altout ti3026_output = { 677static struct matrox_altout ti3026_output = {
671 .name = "Primary output", 678 .name = "Primary output",
672}; 679};
673 680
674static int Ti3026_preinit(WPMINFO2) { 681static int Ti3026_preinit(struct matrox_fb_info *minfo)
682{
675 static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, 683 static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960,
676 1024, 1152, 1280, 1600, 1664, 1920, 684 1024, 1152, 1280, 1600, 1664, 1920,
677 2048, 0}; 685 2048, 0};
678 static const int vxres_mill1[] = { 640, 768, 800, 960, 686 static const int vxres_mill1[] = { 640, 768, 800, 960,
679 1024, 1152, 1280, 1600, 1920, 687 1024, 1152, 1280, 1600, 1920,
680 2048, 0}; 688 2048, 0};
681 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); 689 struct matrox_hw_state *hw = &minfo->hw;
682 690
683 DBG(__func__) 691 DBG(__func__)
684 692
685 ACCESS_FBINFO(millenium) = 1; 693 minfo->millenium = 1;
686 ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL); 694 minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL);
687 ACCESS_FBINFO(capable.cfb4) = 1; 695 minfo->capable.cfb4 = 1;
688 ACCESS_FBINFO(capable.text) = 1; /* isMilleniumII(MINFO); */ 696 minfo->capable.text = 1; /* isMilleniumII(minfo); */
689 ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1; 697 minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1;
690 698
691 ACCESS_FBINFO(outputs[0]).data = MINFO; 699 minfo->outputs[0].data = minfo;
692 ACCESS_FBINFO(outputs[0]).output = &ti3026_output; 700 minfo->outputs[0].output = &ti3026_output;
693 ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; 701 minfo->outputs[0].src = minfo->outputs[0].default_src;
694 ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 702 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
695 703
696 if (ACCESS_FBINFO(devflags.noinit)) 704 if (minfo->devflags.noinit)
697 return 0; 705 return 0;
698 /* preserve VGA I/O, BIOS and PPC */ 706 /* preserve VGA I/O, BIOS and PPC */
699 hw->MXoptionReg &= 0xC0000100; 707 hw->MXoptionReg &= 0xC0000100;
700 hw->MXoptionReg |= 0x002C0000; 708 hw->MXoptionReg |= 0x002C0000;
701 if (ACCESS_FBINFO(devflags.novga)) 709 if (minfo->devflags.novga)
702 hw->MXoptionReg &= ~0x00000100; 710 hw->MXoptionReg &= ~0x00000100;
703 if (ACCESS_FBINFO(devflags.nobios)) 711 if (minfo->devflags.nobios)
704 hw->MXoptionReg &= ~0x40000000; 712 hw->MXoptionReg &= ~0x40000000;
705 if (ACCESS_FBINFO(devflags.nopciretry)) 713 if (minfo->devflags.nopciretry)
706 hw->MXoptionReg |= 0x20000000; 714 hw->MXoptionReg |= 0x20000000;
707 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); 715 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
708 716
709 ACCESS_FBINFO(accel.ramdac_rev) = inTi3026(PMINFO TVP3026_XSILICONREV); 717 minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV);
710 718
711 outTi3026(PMINFO TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED); 719 outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
712 outTi3026(PMINFO TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR); 720 outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
713 outTi3026(PMINFO TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA); 721 outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
714 722
715 outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); 723 outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
716 outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0x00); 724 outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00);
717 outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00); 725 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
718 726
719 mga_outb(M_MISC_REG, 0x67); 727 mga_outb(M_MISC_REG, 0x67);
720 728
721 outTi3026(PMINFO TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); 729 outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
722 730
723 mga_outl(M_RESET, 1); 731 mga_outl(M_RESET, 1);
724 udelay(250); 732 udelay(250);
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 9c3aeee1cc4f..8335a6fe303e 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -81,7 +81,7 @@
81#include "matroxfb_Ti3026.h" 81#include "matroxfb_Ti3026.h"
82#include "matroxfb_misc.h" 82#include "matroxfb_misc.h"
83 83
84#define curr_ydstorg(x) ACCESS_FBINFO2(x, curr.ydstorg.pixels) 84#define curr_ydstorg(x) ((x)->curr.ydstorg.pixels)
85 85
86#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l)) 86#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
87 87
@@ -107,7 +107,8 @@ static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* imag
107static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect); 107static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
108static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area); 108static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area);
109 109
110void matrox_cfbX_init(WPMINFO2) { 110void matrox_cfbX_init(struct matrox_fb_info *minfo)
111{
111 u_int32_t maccess; 112 u_int32_t maccess;
112 u_int32_t mpitch; 113 u_int32_t mpitch;
113 u_int32_t mopmode; 114 u_int32_t mopmode;
@@ -115,59 +116,59 @@ void matrox_cfbX_init(WPMINFO2) {
115 116
116 DBG(__func__) 117 DBG(__func__)
117 118
118 mpitch = ACCESS_FBINFO(fbcon).var.xres_virtual; 119 mpitch = minfo->fbcon.var.xres_virtual;
119 120
120 ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; 121 minfo->fbops.fb_copyarea = cfb_copyarea;
121 ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; 122 minfo->fbops.fb_fillrect = cfb_fillrect;
122 ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; 123 minfo->fbops.fb_imageblit = cfb_imageblit;
123 ACCESS_FBINFO(fbops).fb_cursor = NULL; 124 minfo->fbops.fb_cursor = NULL;
124 125
125 accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; 126 accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT;
126 127
127 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { 128 switch (minfo->fbcon.var.bits_per_pixel) {
128 case 4: maccess = 0x00000000; /* accelerate as 8bpp video */ 129 case 4: maccess = 0x00000000; /* accelerate as 8bpp video */
129 mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */ 130 mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
130 mopmode = M_OPMODE_4BPP; 131 mopmode = M_OPMODE_4BPP;
131 matrox_cfb4_pal(ACCESS_FBINFO(cmap)); 132 matrox_cfb4_pal(minfo->cmap);
132 if (accel && !(mpitch & 1)) { 133 if (accel && !(mpitch & 1)) {
133 ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_cfb4_copyarea; 134 minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea;
134 ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_cfb4_fillrect; 135 minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect;
135 } 136 }
136 break; 137 break;
137 case 8: maccess = 0x00000000; 138 case 8: maccess = 0x00000000;
138 mopmode = M_OPMODE_8BPP; 139 mopmode = M_OPMODE_8BPP;
139 matrox_cfb8_pal(ACCESS_FBINFO(cmap)); 140 matrox_cfb8_pal(minfo->cmap);
140 if (accel) { 141 if (accel) {
141 ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; 142 minfo->fbops.fb_copyarea = matroxfb_copyarea;
142 ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; 143 minfo->fbops.fb_fillrect = matroxfb_fillrect;
143 ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; 144 minfo->fbops.fb_imageblit = matroxfb_imageblit;
144 } 145 }
145 break; 146 break;
146 case 16: if (ACCESS_FBINFO(fbcon).var.green.length == 5) 147 case 16: if (minfo->fbcon.var.green.length == 5)
147 maccess = 0xC0000001; 148 maccess = 0xC0000001;
148 else 149 else
149 maccess = 0x40000001; 150 maccess = 0x40000001;
150 mopmode = M_OPMODE_16BPP; 151 mopmode = M_OPMODE_16BPP;
151 if (accel) { 152 if (accel) {
152 ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; 153 minfo->fbops.fb_copyarea = matroxfb_copyarea;
153 ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; 154 minfo->fbops.fb_fillrect = matroxfb_fillrect;
154 ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; 155 minfo->fbops.fb_imageblit = matroxfb_imageblit;
155 } 156 }
156 break; 157 break;
157 case 24: maccess = 0x00000003; 158 case 24: maccess = 0x00000003;
158 mopmode = M_OPMODE_24BPP; 159 mopmode = M_OPMODE_24BPP;
159 if (accel) { 160 if (accel) {
160 ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; 161 minfo->fbops.fb_copyarea = matroxfb_copyarea;
161 ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; 162 minfo->fbops.fb_fillrect = matroxfb_fillrect;
162 ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; 163 minfo->fbops.fb_imageblit = matroxfb_imageblit;
163 } 164 }
164 break; 165 break;
165 case 32: maccess = 0x00000002; 166 case 32: maccess = 0x00000002;
166 mopmode = M_OPMODE_32BPP; 167 mopmode = M_OPMODE_32BPP;
167 if (accel) { 168 if (accel) {
168 ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; 169 minfo->fbops.fb_copyarea = matroxfb_copyarea;
169 ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; 170 minfo->fbops.fb_fillrect = matroxfb_fillrect;
170 ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; 171 minfo->fbops.fb_imageblit = matroxfb_imageblit;
171 } 172 }
172 break; 173 break;
173 default: maccess = 0x00000000; 174 default: maccess = 0x00000000;
@@ -176,10 +177,10 @@ void matrox_cfbX_init(WPMINFO2) {
176 } 177 }
177 mga_fifo(8); 178 mga_fifo(8);
178 mga_outl(M_PITCH, mpitch); 179 mga_outl(M_PITCH, mpitch);
179 mga_outl(M_YDSTORG, curr_ydstorg(MINFO)); 180 mga_outl(M_YDSTORG, curr_ydstorg(minfo));
180 if (ACCESS_FBINFO(capable.plnwt)) 181 if (minfo->capable.plnwt)
181 mga_outl(M_PLNWT, -1); 182 mga_outl(M_PLNWT, -1);
182 if (ACCESS_FBINFO(capable.srcorg)) { 183 if (minfo->capable.srcorg) {
183 mga_outl(M_SRCORG, 0); 184 mga_outl(M_SRCORG, 0);
184 mga_outl(M_DSTORG, 0); 185 mga_outl(M_DSTORG, 0);
185 } 186 }
@@ -188,14 +189,16 @@ void matrox_cfbX_init(WPMINFO2) {
188 mga_outl(M_YTOP, 0); 189 mga_outl(M_YTOP, 0);
189 mga_outl(M_YBOT, 0x01FFFFFF); 190 mga_outl(M_YBOT, 0x01FFFFFF);
190 mga_outl(M_MACCESS, maccess); 191 mga_outl(M_MACCESS, maccess);
191 ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; 192 minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
192 if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC; 193 if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
193 ACCESS_FBINFO(accel.m_opmode) = mopmode; 194 minfo->accel.m_opmode = mopmode;
194} 195}
195 196
196EXPORT_SYMBOL(matrox_cfbX_init); 197EXPORT_SYMBOL(matrox_cfbX_init);
197 198
198static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx, int height, int width) { 199static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
200 int sx, int dy, int dx, int height, int width)
201{
199 int start, end; 202 int start, end;
200 CRITFLAGS 203 CRITFLAGS
201 204
@@ -209,7 +212,7 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx
209 M_DWG_BFCOL | M_DWG_REPLACE); 212 M_DWG_BFCOL | M_DWG_REPLACE);
210 mga_outl(M_AR5, vxres); 213 mga_outl(M_AR5, vxres);
211 width--; 214 width--;
212 start = sy*vxres+sx+curr_ydstorg(MINFO); 215 start = sy*vxres+sx+curr_ydstorg(minfo);
213 end = start+width; 216 end = start+width;
214 } else { 217 } else {
215 mga_fifo(3); 218 mga_fifo(3);
@@ -217,7 +220,7 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx
217 mga_outl(M_SGN, 5); 220 mga_outl(M_SGN, 5);
218 mga_outl(M_AR5, -vxres); 221 mga_outl(M_AR5, -vxres);
219 width--; 222 width--;
220 end = (sy+height-1)*vxres+sx+curr_ydstorg(MINFO); 223 end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
221 start = end+width; 224 start = end+width;
222 dy += height-1; 225 dy += height-1;
223 } 226 }
@@ -231,7 +234,10 @@ static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx
231 CRITEND 234 CRITEND
232} 235}
233 236
234static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, int dx, int height, int width) { 237static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
238 int sy, int sx, int dy, int dx, int height,
239 int width)
240{
235 int start, end; 241 int start, end;
236 CRITFLAGS 242 CRITFLAGS
237 243
@@ -245,7 +251,7 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in
245 M_DWG_BFCOL | M_DWG_REPLACE); 251 M_DWG_BFCOL | M_DWG_REPLACE);
246 mga_outl(M_AR5, vxres); 252 mga_outl(M_AR5, vxres);
247 width--; 253 width--;
248 start = sy*vxres+sx+curr_ydstorg(MINFO); 254 start = sy*vxres+sx+curr_ydstorg(minfo);
249 end = start+width; 255 end = start+width;
250 } else { 256 } else {
251 mga_fifo(3); 257 mga_fifo(3);
@@ -253,7 +259,7 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in
253 mga_outl(M_SGN, 5); 259 mga_outl(M_SGN, 5);
254 mga_outl(M_AR5, -vxres); 260 mga_outl(M_AR5, -vxres);
255 width--; 261 width--;
256 end = (sy+height-1)*vxres+sx+curr_ydstorg(MINFO); 262 end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
257 start = end+width; 263 start = end+width;
258 dy += height-1; 264 dy += height-1;
259 } 265 }
@@ -269,22 +275,23 @@ static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, in
269} 275}
270 276
271static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) { 277static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
272 MINFO_FROM_INFO(info); 278 struct matrox_fb_info *minfo = info2minfo(info);
273 279
274 if ((area->sx | area->dx | area->width) & 1) 280 if ((area->sx | area->dx | area->width) & 1)
275 cfb_copyarea(info, area); 281 cfb_copyarea(info, area);
276 else 282 else
277 matrox_accel_bmove_lin(PMINFO ACCESS_FBINFO(fbcon.var.xres_virtual) >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1); 283 matrox_accel_bmove_lin(minfo, minfo->fbcon.var.xres_virtual >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1);
278} 284}
279 285
280static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) { 286static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
281 MINFO_FROM_INFO(info); 287 struct matrox_fb_info *minfo = info2minfo(info);
282 288
283 matrox_accel_bmove(PMINFO ACCESS_FBINFO(fbcon.var.xres_virtual), area->sy, area->sx, area->dy, area->dx, area->height, area->width); 289 matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width);
284} 290}
285 291
286static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int height, 292static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
287 int width) { 293 int sy, int sx, int height, int width)
294{
288 CRITFLAGS 295 CRITFLAGS
289 296
290 DBG(__func__) 297 DBG(__func__)
@@ -292,7 +299,7 @@ static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int he
292 CRITBEGIN 299 CRITBEGIN
293 300
294 mga_fifo(5); 301 mga_fifo(5);
295 mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE); 302 mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
296 mga_outl(M_FCOL, color); 303 mga_outl(M_FCOL, color);
297 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); 304 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
298 mga_ydstlen(sy, height); 305 mga_ydstlen(sy, height);
@@ -302,16 +309,18 @@ static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int he
302} 309}
303 310
304static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { 311static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
305 MINFO_FROM_INFO(info); 312 struct matrox_fb_info *minfo = info2minfo(info);
306 313
307 switch (rect->rop) { 314 switch (rect->rop) {
308 case ROP_COPY: 315 case ROP_COPY:
309 matroxfb_accel_clear(PMINFO ((u_int32_t*)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); 316 matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
310 break; 317 break;
311 } 318 }
312} 319}
313 320
314static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int height, int width) { 321static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
322 int sy, int sx, int height, int width)
323{
315 int whattodo; 324 int whattodo;
316 CRITFLAGS 325 CRITFLAGS
317 326
@@ -333,16 +342,16 @@ static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int heigh
333 sx >>= 1; 342 sx >>= 1;
334 if (width) { 343 if (width) {
335 mga_fifo(5); 344 mga_fifo(5);
336 mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE2); 345 mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
337 mga_outl(M_FCOL, bgx); 346 mga_outl(M_FCOL, bgx);
338 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); 347 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
339 mga_outl(M_YDST, sy * ACCESS_FBINFO(fbcon).var.xres_virtual >> 6); 348 mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6);
340 mga_outl(M_LEN | M_EXEC, height); 349 mga_outl(M_LEN | M_EXEC, height);
341 WaitTillIdle(); 350 WaitTillIdle();
342 } 351 }
343 if (whattodo) { 352 if (whattodo) {
344 u_int32_t step = ACCESS_FBINFO(fbcon).var.xres_virtual >> 1; 353 u_int32_t step = minfo->fbcon.var.xres_virtual >> 1;
345 vaddr_t vbase = ACCESS_FBINFO(video.vbase); 354 vaddr_t vbase = minfo->video.vbase;
346 if (whattodo & 1) { 355 if (whattodo & 1) {
347 unsigned int uaddr = sy * step + sx - 1; 356 unsigned int uaddr = sy * step + sx - 1;
348 u_int32_t loop; 357 u_int32_t loop;
@@ -367,17 +376,19 @@ static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int heigh
367} 376}
368 377
369static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { 378static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
370 MINFO_FROM_INFO(info); 379 struct matrox_fb_info *minfo = info2minfo(info);
371 380
372 switch (rect->rop) { 381 switch (rect->rop) {
373 case ROP_COPY: 382 case ROP_COPY:
374 matroxfb_cfb4_clear(PMINFO ((u_int32_t*)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); 383 matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
375 break; 384 break;
376 } 385 }
377} 386}
378 387
379static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx, 388static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
380 const u_int8_t* chardata, int width, int height, int yy, int xx) { 389 u_int32_t bgx, const u_int8_t *chardata,
390 int width, int height, int yy, int xx)
391{
381 u_int32_t step; 392 u_int32_t step;
382 u_int32_t ydstlen; 393 u_int32_t ydstlen;
383 u_int32_t xlen; 394 u_int32_t xlen;
@@ -412,7 +423,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
412 mga_outl(M_FCOL, fgx); 423 mga_outl(M_FCOL, fgx);
413 mga_outl(M_BCOL, bgx); 424 mga_outl(M_BCOL, bgx);
414 fxbndry = ((xx + width - 1) << 16) | xx; 425 fxbndry = ((xx + width - 1) << 16) | xx;
415 mmio = ACCESS_FBINFO(mmio.vbase); 426 mmio = minfo->mmio.vbase;
416 427
417 mga_fifo(6); 428 mga_fifo(6);
418 mga_writel(mmio, M_FXBNDRY, fxbndry); 429 mga_writel(mmio, M_FXBNDRY, fxbndry);
@@ -467,7 +478,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
467 478
468 479
469static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) { 480static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) {
470 MINFO_FROM_INFO(info); 481 struct matrox_fb_info *minfo = info2minfo(info);
471 482
472 DBG_HEAVY(__func__); 483 DBG_HEAVY(__func__);
473 484
@@ -476,7 +487,7 @@ static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* imag
476 487
477 fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color]; 488 fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color];
478 bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color]; 489 bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color];
479 matroxfb_1bpp_imageblit(PMINFO fgx, bgx, image->data, image->width, image->height, image->dy, image->dx); 490 matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx);
480 } else { 491 } else {
481 /* Danger! image->depth is useless: logo painting code always 492 /* Danger! image->depth is useless: logo painting code always
482 passes framebuffer color depth here, although logo data are 493 passes framebuffer color depth here, although logo data are
diff --git a/drivers/video/matrox/matroxfb_accel.h b/drivers/video/matrox/matroxfb_accel.h
index f40c314b4c30..1e418e62c22d 100644
--- a/drivers/video/matrox/matroxfb_accel.h
+++ b/drivers/video/matrox/matroxfb_accel.h
@@ -3,6 +3,6 @@
3 3
4#include "matroxfb_base.h" 4#include "matroxfb_base.h"
5 5
6void matrox_cfbX_init(WPMINFO2); 6void matrox_cfbX_init(struct matrox_fb_info *minfo);
7 7
8#endif 8#endif
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 8e7a275df50c..7064fb4427b6 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -154,21 +154,22 @@ static struct fb_var_screeninfo vesafb_defined = {
154 154
155 155
156/* --------------------------------------------------------------------- */ 156/* --------------------------------------------------------------------- */
157static void update_crtc2(WPMINFO unsigned int pos) { 157static void update_crtc2(struct matrox_fb_info *minfo, unsigned int pos)
158 struct matroxfb_dh_fb_info* info = ACCESS_FBINFO(crtc2.info); 158{
159 struct matroxfb_dh_fb_info *info = minfo->crtc2.info;
159 160
160 /* Make sure that displays are compatible */ 161 /* Make sure that displays are compatible */
161 if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel) 162 if (info && (info->fbcon.var.bits_per_pixel == minfo->fbcon.var.bits_per_pixel)
162 && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual) 163 && (info->fbcon.var.xres_virtual == minfo->fbcon.var.xres_virtual)
163 && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length) 164 && (info->fbcon.var.green.length == minfo->fbcon.var.green.length)
164 ) { 165 ) {
165 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { 166 switch (minfo->fbcon.var.bits_per_pixel) {
166 case 16: 167 case 16:
167 case 32: 168 case 32:
168 pos = pos * 8; 169 pos = pos * 8;
169 if (info->interlaced) { 170 if (info->interlaced) {
170 mga_outl(0x3C2C, pos); 171 mga_outl(0x3C2C, pos);
171 mga_outl(0x3C28, pos + ACCESS_FBINFO(fbcon).var.xres_virtual * ACCESS_FBINFO(fbcon).var.bits_per_pixel / 8); 172 mga_outl(0x3C28, pos + minfo->fbcon.var.xres_virtual * minfo->fbcon.var.bits_per_pixel / 8);
172 } else { 173 } else {
173 mga_outl(0x3C28, pos); 174 mga_outl(0x3C28, pos);
174 } 175 }
@@ -177,17 +178,18 @@ static void update_crtc2(WPMINFO unsigned int pos) {
177 } 178 }
178} 179}
179 180
180static void matroxfb_crtc1_panpos(WPMINFO2) { 181static void matroxfb_crtc1_panpos(struct matrox_fb_info *minfo)
181 if (ACCESS_FBINFO(crtc1.panpos) >= 0) { 182{
183 if (minfo->crtc1.panpos >= 0) {
182 unsigned long flags; 184 unsigned long flags;
183 int panpos; 185 int panpos;
184 186
185 matroxfb_DAC_lock_irqsave(flags); 187 matroxfb_DAC_lock_irqsave(flags);
186 panpos = ACCESS_FBINFO(crtc1.panpos); 188 panpos = minfo->crtc1.panpos;
187 if (panpos >= 0) { 189 if (panpos >= 0) {
188 unsigned int extvga_reg; 190 unsigned int extvga_reg;
189 191
190 ACCESS_FBINFO(crtc1.panpos) = -1; /* No update pending anymore */ 192 minfo->crtc1.panpos = -1; /* No update pending anymore */
191 extvga_reg = mga_inb(M_EXTVGA_INDEX); 193 extvga_reg = mga_inb(M_EXTVGA_INDEX);
192 mga_setr(M_EXTVGA_INDEX, 0x00, panpos); 194 mga_setr(M_EXTVGA_INDEX, 0x00, panpos);
193 if (extvga_reg != 0x00) { 195 if (extvga_reg != 0x00) {
@@ -202,39 +204,39 @@ static irqreturn_t matrox_irq(int irq, void *dev_id)
202{ 204{
203 u_int32_t status; 205 u_int32_t status;
204 int handled = 0; 206 int handled = 0;
205 207 struct matrox_fb_info *minfo = dev_id;
206 MINFO_FROM(dev_id);
207 208
208 status = mga_inl(M_STATUS); 209 status = mga_inl(M_STATUS);
209 210
210 if (status & 0x20) { 211 if (status & 0x20) {
211 mga_outl(M_ICLEAR, 0x20); 212 mga_outl(M_ICLEAR, 0x20);
212 ACCESS_FBINFO(crtc1.vsync.cnt)++; 213 minfo->crtc1.vsync.cnt++;
213 matroxfb_crtc1_panpos(PMINFO2); 214 matroxfb_crtc1_panpos(minfo);
214 wake_up_interruptible(&ACCESS_FBINFO(crtc1.vsync.wait)); 215 wake_up_interruptible(&minfo->crtc1.vsync.wait);
215 handled = 1; 216 handled = 1;
216 } 217 }
217 if (status & 0x200) { 218 if (status & 0x200) {
218 mga_outl(M_ICLEAR, 0x200); 219 mga_outl(M_ICLEAR, 0x200);
219 ACCESS_FBINFO(crtc2.vsync.cnt)++; 220 minfo->crtc2.vsync.cnt++;
220 wake_up_interruptible(&ACCESS_FBINFO(crtc2.vsync.wait)); 221 wake_up_interruptible(&minfo->crtc2.vsync.wait);
221 handled = 1; 222 handled = 1;
222 } 223 }
223 return IRQ_RETVAL(handled); 224 return IRQ_RETVAL(handled);
224} 225}
225 226
226int matroxfb_enable_irq(WPMINFO int reenable) { 227int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable)
228{
227 u_int32_t bm; 229 u_int32_t bm;
228 230
229 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) 231 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
230 bm = 0x220; 232 bm = 0x220;
231 else 233 else
232 bm = 0x020; 234 bm = 0x020;
233 235
234 if (!test_and_set_bit(0, &ACCESS_FBINFO(irq_flags))) { 236 if (!test_and_set_bit(0, &minfo->irq_flags)) {
235 if (request_irq(ACCESS_FBINFO(pcidev)->irq, matrox_irq, 237 if (request_irq(minfo->pcidev->irq, matrox_irq,
236 IRQF_SHARED, "matroxfb", MINFO)) { 238 IRQF_SHARED, "matroxfb", minfo)) {
237 clear_bit(0, &ACCESS_FBINFO(irq_flags)); 239 clear_bit(0, &minfo->irq_flags);
238 return -EINVAL; 240 return -EINVAL;
239 } 241 }
240 /* Clear any pending field interrupts */ 242 /* Clear any pending field interrupts */
@@ -252,37 +254,39 @@ int matroxfb_enable_irq(WPMINFO int reenable) {
252 return 0; 254 return 0;
253} 255}
254 256
255static void matroxfb_disable_irq(WPMINFO2) { 257static void matroxfb_disable_irq(struct matrox_fb_info *minfo)
256 if (test_and_clear_bit(0, &ACCESS_FBINFO(irq_flags))) { 258{
259 if (test_and_clear_bit(0, &minfo->irq_flags)) {
257 /* Flush pending pan-at-vbl request... */ 260 /* Flush pending pan-at-vbl request... */
258 matroxfb_crtc1_panpos(PMINFO2); 261 matroxfb_crtc1_panpos(minfo);
259 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) 262 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
260 mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220); 263 mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220);
261 else 264 else
262 mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20); 265 mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20);
263 free_irq(ACCESS_FBINFO(pcidev)->irq, MINFO); 266 free_irq(minfo->pcidev->irq, minfo);
264 } 267 }
265} 268}
266 269
267int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { 270int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc)
271{
268 struct matrox_vsync *vs; 272 struct matrox_vsync *vs;
269 unsigned int cnt; 273 unsigned int cnt;
270 int ret; 274 int ret;
271 275
272 switch (crtc) { 276 switch (crtc) {
273 case 0: 277 case 0:
274 vs = &ACCESS_FBINFO(crtc1.vsync); 278 vs = &minfo->crtc1.vsync;
275 break; 279 break;
276 case 1: 280 case 1:
277 if (ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG400) { 281 if (minfo->devflags.accelerator != FB_ACCEL_MATROX_MGAG400) {
278 return -ENODEV; 282 return -ENODEV;
279 } 283 }
280 vs = &ACCESS_FBINFO(crtc2.vsync); 284 vs = &minfo->crtc2.vsync;
281 break; 285 break;
282 default: 286 default:
283 return -ENODEV; 287 return -ENODEV;
284 } 288 }
285 ret = matroxfb_enable_irq(PMINFO 0); 289 ret = matroxfb_enable_irq(minfo, 0);
286 if (ret) { 290 if (ret) {
287 return ret; 291 return ret;
288 } 292 }
@@ -293,7 +297,7 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
293 return ret; 297 return ret;
294 } 298 }
295 if (ret == 0) { 299 if (ret == 0) {
296 matroxfb_enable_irq(PMINFO 1); 300 matroxfb_enable_irq(minfo, 1);
297 return -ETIMEDOUT; 301 return -ETIMEDOUT;
298 } 302 }
299 return 0; 303 return 0;
@@ -301,12 +305,12 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
301 305
302/* --------------------------------------------------------------------- */ 306/* --------------------------------------------------------------------- */
303 307
304static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { 308static void matrox_pan_var(struct matrox_fb_info *minfo,
309 struct fb_var_screeninfo *var)
310{
305 unsigned int pos; 311 unsigned int pos;
306 unsigned short p0, p1, p2; 312 unsigned short p0, p1, p2;
307#ifdef CONFIG_FB_MATROX_32MB
308 unsigned int p3; 313 unsigned int p3;
309#endif
310 int vbl; 314 int vbl;
311 unsigned long flags; 315 unsigned long flags;
312 316
@@ -314,47 +318,44 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
314 318
315 DBG(__func__) 319 DBG(__func__)
316 320
317 if (ACCESS_FBINFO(dead)) 321 if (minfo->dead)
318 return; 322 return;
319 323
320 ACCESS_FBINFO(fbcon).var.xoffset = var->xoffset; 324 minfo->fbcon.var.xoffset = var->xoffset;
321 ACCESS_FBINFO(fbcon).var.yoffset = var->yoffset; 325 minfo->fbcon.var.yoffset = var->yoffset;
322 pos = (ACCESS_FBINFO(fbcon).var.yoffset * ACCESS_FBINFO(fbcon).var.xres_virtual + ACCESS_FBINFO(fbcon).var.xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; 326 pos = (minfo->fbcon.var.yoffset * minfo->fbcon.var.xres_virtual + minfo->fbcon.var.xoffset) * minfo->curr.final_bppShift / 32;
323 pos += ACCESS_FBINFO(curr.ydstorg.chunks); 327 pos += minfo->curr.ydstorg.chunks;
324 p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF; 328 p0 = minfo->hw.CRTC[0x0D] = pos & 0xFF;
325 p1 = ACCESS_FBINFO(hw).CRTC[0x0C] = (pos & 0xFF00) >> 8; 329 p1 = minfo->hw.CRTC[0x0C] = (pos & 0xFF00) >> 8;
326 p2 = ACCESS_FBINFO(hw).CRTCEXT[0] = (ACCESS_FBINFO(hw).CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); 330 p2 = minfo->hw.CRTCEXT[0] = (minfo->hw.CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
327#ifdef CONFIG_FB_MATROX_32MB 331 p3 = minfo->hw.CRTCEXT[8] = pos >> 21;
328 p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21;
329#endif
330 332
331 /* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */ 333 /* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */
332 vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(PMINFO 0) == 0); 334 vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(minfo, 0) == 0);
333 335
334 CRITBEGIN 336 CRITBEGIN
335 337
336 matroxfb_DAC_lock_irqsave(flags); 338 matroxfb_DAC_lock_irqsave(flags);
337 mga_setr(M_CRTC_INDEX, 0x0D, p0); 339 mga_setr(M_CRTC_INDEX, 0x0D, p0);
338 mga_setr(M_CRTC_INDEX, 0x0C, p1); 340 mga_setr(M_CRTC_INDEX, 0x0C, p1);
339#ifdef CONFIG_FB_MATROX_32MB 341 if (minfo->devflags.support32MB)
340 if (ACCESS_FBINFO(devflags.support32MB))
341 mga_setr(M_EXTVGA_INDEX, 0x08, p3); 342 mga_setr(M_EXTVGA_INDEX, 0x08, p3);
342#endif
343 if (vbl) { 343 if (vbl) {
344 ACCESS_FBINFO(crtc1.panpos) = p2; 344 minfo->crtc1.panpos = p2;
345 } else { 345 } else {
346 /* Abort any pending change */ 346 /* Abort any pending change */
347 ACCESS_FBINFO(crtc1.panpos) = -1; 347 minfo->crtc1.panpos = -1;
348 mga_setr(M_EXTVGA_INDEX, 0x00, p2); 348 mga_setr(M_EXTVGA_INDEX, 0x00, p2);
349 } 349 }
350 matroxfb_DAC_unlock_irqrestore(flags); 350 matroxfb_DAC_unlock_irqrestore(flags);
351 351
352 update_crtc2(PMINFO pos); 352 update_crtc2(minfo, pos);
353 353
354 CRITEND 354 CRITEND
355} 355}
356 356
357static void matroxfb_remove(WPMINFO int dummy) { 357static void matroxfb_remove(struct matrox_fb_info *minfo, int dummy)
358{
358 /* Currently we are holding big kernel lock on all dead & usecount updates. 359 /* Currently we are holding big kernel lock on all dead & usecount updates.
359 * Destroy everything after all users release it. Especially do not unregister 360 * Destroy everything after all users release it. Especially do not unregister
360 * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check 361 * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check
@@ -363,25 +364,23 @@ static void matroxfb_remove(WPMINFO int dummy) {
363 * write data without causing too much damage... 364 * write data without causing too much damage...
364 */ 365 */
365 366
366 ACCESS_FBINFO(dead) = 1; 367 minfo->dead = 1;
367 if (ACCESS_FBINFO(usecount)) { 368 if (minfo->usecount) {
368 /* destroy it later */ 369 /* destroy it later */
369 return; 370 return;
370 } 371 }
371 matroxfb_unregister_device(MINFO); 372 matroxfb_unregister_device(minfo);
372 unregister_framebuffer(&ACCESS_FBINFO(fbcon)); 373 unregister_framebuffer(&minfo->fbcon);
373 matroxfb_g450_shutdown(PMINFO2); 374 matroxfb_g450_shutdown(minfo);
374#ifdef CONFIG_MTRR 375#ifdef CONFIG_MTRR
375 if (ACCESS_FBINFO(mtrr.vram_valid)) 376 if (minfo->mtrr.vram_valid)
376 mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len)); 377 mtrr_del(minfo->mtrr.vram, minfo->video.base, minfo->video.len);
377#endif 378#endif
378 mga_iounmap(ACCESS_FBINFO(mmio.vbase)); 379 mga_iounmap(minfo->mmio.vbase);
379 mga_iounmap(ACCESS_FBINFO(video.vbase)); 380 mga_iounmap(minfo->video.vbase);
380 release_mem_region(ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len_maximum)); 381 release_mem_region(minfo->video.base, minfo->video.len_maximum);
381 release_mem_region(ACCESS_FBINFO(mmio.base), 16384); 382 release_mem_region(minfo->mmio.base, 16384);
382#ifdef CONFIG_FB_MATROX_MULTIHEAD
383 kfree(minfo); 383 kfree(minfo);
384#endif
385} 384}
386 385
387 /* 386 /*
@@ -390,48 +389,50 @@ static void matroxfb_remove(WPMINFO int dummy) {
390 389
391static int matroxfb_open(struct fb_info *info, int user) 390static int matroxfb_open(struct fb_info *info, int user)
392{ 391{
393 MINFO_FROM_INFO(info); 392 struct matrox_fb_info *minfo = info2minfo(info);
394 393
395 DBG_LOOP(__func__) 394 DBG_LOOP(__func__)
396 395
397 if (ACCESS_FBINFO(dead)) { 396 if (minfo->dead) {
398 return -ENXIO; 397 return -ENXIO;
399 } 398 }
400 ACCESS_FBINFO(usecount)++; 399 minfo->usecount++;
401 if (user) { 400 if (user) {
402 ACCESS_FBINFO(userusecount)++; 401 minfo->userusecount++;
403 } 402 }
404 return(0); 403 return(0);
405} 404}
406 405
407static int matroxfb_release(struct fb_info *info, int user) 406static int matroxfb_release(struct fb_info *info, int user)
408{ 407{
409 MINFO_FROM_INFO(info); 408 struct matrox_fb_info *minfo = info2minfo(info);
410 409
411 DBG_LOOP(__func__) 410 DBG_LOOP(__func__)
412 411
413 if (user) { 412 if (user) {
414 if (0 == --ACCESS_FBINFO(userusecount)) { 413 if (0 == --minfo->userusecount) {
415 matroxfb_disable_irq(PMINFO2); 414 matroxfb_disable_irq(minfo);
416 } 415 }
417 } 416 }
418 if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) { 417 if (!(--minfo->usecount) && minfo->dead) {
419 matroxfb_remove(PMINFO 0); 418 matroxfb_remove(minfo, 0);
420 } 419 }
421 return(0); 420 return(0);
422} 421}
423 422
424static int matroxfb_pan_display(struct fb_var_screeninfo *var, 423static int matroxfb_pan_display(struct fb_var_screeninfo *var,
425 struct fb_info* info) { 424 struct fb_info* info) {
426 MINFO_FROM_INFO(info); 425 struct matrox_fb_info *minfo = info2minfo(info);
427 426
428 DBG(__func__) 427 DBG(__func__)
429 428
430 matrox_pan_var(PMINFO var); 429 matrox_pan_var(minfo, var);
431 return 0; 430 return 0;
432} 431}
433 432
434static int matroxfb_get_final_bppShift(CPMINFO int bpp) { 433static int matroxfb_get_final_bppShift(const struct matrox_fb_info *minfo,
434 int bpp)
435{
435 int bppshft2; 436 int bppshft2;
436 437
437 DBG(__func__) 438 DBG(__func__)
@@ -440,14 +441,16 @@ static int matroxfb_get_final_bppShift(CPMINFO int bpp) {
440 if (!bppshft2) { 441 if (!bppshft2) {
441 return 8; 442 return 8;
442 } 443 }
443 if (isInterleave(MINFO)) 444 if (isInterleave(minfo))
444 bppshft2 >>= 1; 445 bppshft2 >>= 1;
445 if (ACCESS_FBINFO(devflags.video64bits)) 446 if (minfo->devflags.video64bits)
446 bppshft2 >>= 1; 447 bppshft2 >>= 1;
447 return bppshft2; 448 return bppshft2;
448} 449}
449 450
450static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) { 451static int matroxfb_test_and_set_rounding(const struct matrox_fb_info *minfo,
452 int xres, int bpp)
453{
451 int over; 454 int over;
452 int rounding; 455 int rounding;
453 456
@@ -465,11 +468,11 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
465 break; 468 break;
466 default: rounding = 16; 469 default: rounding = 16;
467 /* on G400, 16 really does not work */ 470 /* on G400, 16 really does not work */
468 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) 471 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
469 rounding = 32; 472 rounding = 32;
470 break; 473 break;
471 } 474 }
472 if (isInterleave(MINFO)) { 475 if (isInterleave(minfo)) {
473 rounding *= 2; 476 rounding *= 2;
474 } 477 }
475 over = xres % rounding; 478 over = xres % rounding;
@@ -478,7 +481,9 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
478 return xres; 481 return xres;
479} 482}
480 483
481static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) { 484static int matroxfb_pitch_adjust(const struct matrox_fb_info *minfo, int xres,
485 int bpp)
486{
482 const int* width; 487 const int* width;
483 int xres_new; 488 int xres_new;
484 489
@@ -486,18 +491,18 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
486 491
487 if (!bpp) return xres; 492 if (!bpp) return xres;
488 493
489 width = ACCESS_FBINFO(capable.vxres); 494 width = minfo->capable.vxres;
490 495
491 if (ACCESS_FBINFO(devflags.precise_width)) { 496 if (minfo->devflags.precise_width) {
492 while (*width) { 497 while (*width) {
493 if ((*width >= xres) && (matroxfb_test_and_set_rounding(PMINFO *width, bpp) == *width)) { 498 if ((*width >= xres) && (matroxfb_test_and_set_rounding(minfo, *width, bpp) == *width)) {
494 break; 499 break;
495 } 500 }
496 width++; 501 width++;
497 } 502 }
498 xres_new = *width; 503 xres_new = *width;
499 } else { 504 } else {
500 xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp); 505 xres_new = matroxfb_test_and_set_rounding(minfo, xres, bpp);
501 } 506 }
502 return xres_new; 507 return xres_new;
503} 508}
@@ -524,7 +529,10 @@ static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
524 return 16; /* return something reasonable... or panic()? */ 529 return 16; /* return something reasonable... or panic()? */
525} 530}
526 531
527static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) { 532static int matroxfb_decode_var(const struct matrox_fb_info *minfo,
533 struct fb_var_screeninfo *var, int *visual,
534 int *video_cmap_len, unsigned int* ydstorg)
535{
528 struct RGBT { 536 struct RGBT {
529 unsigned char bpp; 537 unsigned char bpp;
530 struct { 538 struct {
@@ -551,7 +559,7 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua
551 DBG(__func__) 559 DBG(__func__)
552 560
553 switch (bpp) { 561 switch (bpp) {
554 case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL; 562 case 4: if (!minfo->capable.cfb4) return -EINVAL;
555 break; 563 break;
556 case 8: break; 564 case 8: break;
557 case 16: break; 565 case 16: break;
@@ -560,13 +568,13 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua
560 default: return -EINVAL; 568 default: return -EINVAL;
561 } 569 }
562 *ydstorg = 0; 570 *ydstorg = 0;
563 vramlen = ACCESS_FBINFO(video.len_usable); 571 vramlen = minfo->video.len_usable;
564 if (var->yres_virtual < var->yres) 572 if (var->yres_virtual < var->yres)
565 var->yres_virtual = var->yres; 573 var->yres_virtual = var->yres;
566 if (var->xres_virtual < var->xres) 574 if (var->xres_virtual < var->xres)
567 var->xres_virtual = var->xres; 575 var->xres_virtual = var->xres;
568 576
569 var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, bpp); 577 var->xres_virtual = matroxfb_pitch_adjust(minfo, var->xres_virtual, bpp);
570 memlen = var->xres_virtual * bpp * var->yres_virtual / 8; 578 memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
571 if (memlen > vramlen) { 579 if (memlen > vramlen) {
572 var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp); 580 var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp);
@@ -575,7 +583,7 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua
575 /* There is hardware bug that no line can cross 4MB boundary */ 583 /* There is hardware bug that no line can cross 4MB boundary */
576 /* give up for CFB24, it is impossible to easy workaround it */ 584 /* give up for CFB24, it is impossible to easy workaround it */
577 /* for other try to do something */ 585 /* for other try to do something */
578 if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) { 586 if (!minfo->capable.cross4MB && (memlen > 0x400000)) {
579 if (bpp == 24) { 587 if (bpp == 24) {
580 /* sorry */ 588 /* sorry */
581 } else { 589 } else {
@@ -644,9 +652,7 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
644 unsigned blue, unsigned transp, 652 unsigned blue, unsigned transp,
645 struct fb_info *fb_info) 653 struct fb_info *fb_info)
646{ 654{
647#ifdef CONFIG_FB_MATROX_MULTIHEAD
648 struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon); 655 struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
649#endif
650 656
651 DBG(__func__) 657 DBG(__func__)
652 658
@@ -657,20 +663,20 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
657 * != 0 for invalid regno. 663 * != 0 for invalid regno.
658 */ 664 */
659 665
660 if (regno >= ACCESS_FBINFO(curr.cmap_len)) 666 if (regno >= minfo->curr.cmap_len)
661 return 1; 667 return 1;
662 668
663 if (ACCESS_FBINFO(fbcon).var.grayscale) { 669 if (minfo->fbcon.var.grayscale) {
664 /* gray = 0.30*R + 0.59*G + 0.11*B */ 670 /* gray = 0.30*R + 0.59*G + 0.11*B */
665 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; 671 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
666 } 672 }
667 673
668 red = CNVT_TOHW(red, ACCESS_FBINFO(fbcon).var.red.length); 674 red = CNVT_TOHW(red, minfo->fbcon.var.red.length);
669 green = CNVT_TOHW(green, ACCESS_FBINFO(fbcon).var.green.length); 675 green = CNVT_TOHW(green, minfo->fbcon.var.green.length);
670 blue = CNVT_TOHW(blue, ACCESS_FBINFO(fbcon).var.blue.length); 676 blue = CNVT_TOHW(blue, minfo->fbcon.var.blue.length);
671 transp = CNVT_TOHW(transp, ACCESS_FBINFO(fbcon).var.transp.length); 677 transp = CNVT_TOHW(transp, minfo->fbcon.var.transp.length);
672 678
673 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { 679 switch (minfo->fbcon.var.bits_per_pixel) {
674 case 4: 680 case 4:
675 case 8: 681 case 8:
676 mga_outb(M_DAC_REG, regno); 682 mga_outb(M_DAC_REG, regno);
@@ -683,30 +689,30 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
683 break; 689 break;
684 { 690 {
685 u_int16_t col = 691 u_int16_t col =
686 (red << ACCESS_FBINFO(fbcon).var.red.offset) | 692 (red << minfo->fbcon.var.red.offset) |
687 (green << ACCESS_FBINFO(fbcon).var.green.offset) | 693 (green << minfo->fbcon.var.green.offset) |
688 (blue << ACCESS_FBINFO(fbcon).var.blue.offset) | 694 (blue << minfo->fbcon.var.blue.offset) |
689 (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* for 1:5:5:5 */ 695 (transp << minfo->fbcon.var.transp.offset); /* for 1:5:5:5 */
690 ACCESS_FBINFO(cmap[regno]) = col | (col << 16); 696 minfo->cmap[regno] = col | (col << 16);
691 } 697 }
692 break; 698 break;
693 case 24: 699 case 24:
694 case 32: 700 case 32:
695 if (regno >= 16) 701 if (regno >= 16)
696 break; 702 break;
697 ACCESS_FBINFO(cmap[regno]) = 703 minfo->cmap[regno] =
698 (red << ACCESS_FBINFO(fbcon).var.red.offset) | 704 (red << minfo->fbcon.var.red.offset) |
699 (green << ACCESS_FBINFO(fbcon).var.green.offset) | 705 (green << minfo->fbcon.var.green.offset) |
700 (blue << ACCESS_FBINFO(fbcon).var.blue.offset) | 706 (blue << minfo->fbcon.var.blue.offset) |
701 (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* 8:8:8:8 */ 707 (transp << minfo->fbcon.var.transp.offset); /* 8:8:8:8 */
702 break; 708 break;
703 } 709 }
704 return 0; 710 return 0;
705} 711}
706 712
707static void matroxfb_init_fix(WPMINFO2) 713static void matroxfb_init_fix(struct matrox_fb_info *minfo)
708{ 714{
709 struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; 715 struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
710 DBG(__func__) 716 DBG(__func__)
711 717
712 strcpy(fix->id,"MATROX"); 718 strcpy(fix->id,"MATROX");
@@ -714,18 +720,20 @@ static void matroxfb_init_fix(WPMINFO2)
714 fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */ 720 fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
715 fix->ypanstep = 1; 721 fix->ypanstep = 1;
716 fix->ywrapstep = 0; 722 fix->ywrapstep = 0;
717 fix->mmio_start = ACCESS_FBINFO(mmio.base); 723 fix->mmio_start = minfo->mmio.base;
718 fix->mmio_len = ACCESS_FBINFO(mmio.len); 724 fix->mmio_len = minfo->mmio.len;
719 fix->accel = ACCESS_FBINFO(devflags.accelerator); 725 fix->accel = minfo->devflags.accelerator;
720} 726}
721 727
722static void matroxfb_update_fix(WPMINFO2) 728static void matroxfb_update_fix(struct matrox_fb_info *minfo)
723{ 729{
724 struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; 730 struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
725 DBG(__func__) 731 DBG(__func__)
726 732
727 fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); 733 mutex_lock(&minfo->fbcon.mm_lock);
728 fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); 734 fix->smem_start = minfo->video.base + minfo->curr.ydstorg.bytes;
735 fix->smem_len = minfo->video.len_usable - minfo->curr.ydstorg.bytes;
736 mutex_unlock(&minfo->fbcon.mm_lock);
729} 737}
730 738
731static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 739static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -734,12 +742,12 @@ static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf
734 int visual; 742 int visual;
735 int cmap_len; 743 int cmap_len;
736 unsigned int ydstorg; 744 unsigned int ydstorg;
737 MINFO_FROM_INFO(info); 745 struct matrox_fb_info *minfo = info2minfo(info);
738 746
739 if (ACCESS_FBINFO(dead)) { 747 if (minfo->dead) {
740 return -ENXIO; 748 return -ENXIO;
741 } 749 }
742 if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len, &ydstorg)) != 0) 750 if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
743 return err; 751 return err;
744 return 0; 752 return 0;
745} 753}
@@ -751,35 +759,35 @@ static int matroxfb_set_par(struct fb_info *info)
751 int cmap_len; 759 int cmap_len;
752 unsigned int ydstorg; 760 unsigned int ydstorg;
753 struct fb_var_screeninfo *var; 761 struct fb_var_screeninfo *var;
754 MINFO_FROM_INFO(info); 762 struct matrox_fb_info *minfo = info2minfo(info);
755 763
756 DBG(__func__) 764 DBG(__func__)
757 765
758 if (ACCESS_FBINFO(dead)) { 766 if (minfo->dead) {
759 return -ENXIO; 767 return -ENXIO;
760 } 768 }
761 769
762 var = &info->var; 770 var = &info->var;
763 if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len, &ydstorg)) != 0) 771 if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
764 return err; 772 return err;
765 ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg; 773 minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase) + ydstorg;
766 matroxfb_update_fix(PMINFO2); 774 matroxfb_update_fix(minfo);
767 ACCESS_FBINFO(fbcon).fix.visual = visual; 775 minfo->fbcon.fix.visual = visual;
768 ACCESS_FBINFO(fbcon).fix.type = FB_TYPE_PACKED_PIXELS; 776 minfo->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
769 ACCESS_FBINFO(fbcon).fix.type_aux = 0; 777 minfo->fbcon.fix.type_aux = 0;
770 ACCESS_FBINFO(fbcon).fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3; 778 minfo->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
771 { 779 {
772 unsigned int pos; 780 unsigned int pos;
773 781
774 ACCESS_FBINFO(curr.cmap_len) = cmap_len; 782 minfo->curr.cmap_len = cmap_len;
775 ydstorg += ACCESS_FBINFO(devflags.ydstorg); 783 ydstorg += minfo->devflags.ydstorg;
776 ACCESS_FBINFO(curr.ydstorg.bytes) = ydstorg; 784 minfo->curr.ydstorg.bytes = ydstorg;
777 ACCESS_FBINFO(curr.ydstorg.chunks) = ydstorg >> (isInterleave(MINFO)?3:2); 785 minfo->curr.ydstorg.chunks = ydstorg >> (isInterleave(minfo) ? 3 : 2);
778 if (var->bits_per_pixel == 4) 786 if (var->bits_per_pixel == 4)
779 ACCESS_FBINFO(curr.ydstorg.pixels) = ydstorg; 787 minfo->curr.ydstorg.pixels = ydstorg;
780 else 788 else
781 ACCESS_FBINFO(curr.ydstorg.pixels) = (ydstorg * 8) / var->bits_per_pixel; 789 minfo->curr.ydstorg.pixels = (ydstorg * 8) / var->bits_per_pixel;
782 ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel); 790 minfo->curr.final_bppShift = matroxfb_get_final_bppShift(minfo, var->bits_per_pixel);
783 { struct my_timming mt; 791 { struct my_timming mt;
784 struct matrox_hw_state* hw; 792 struct matrox_hw_state* hw;
785 int out; 793 int out;
@@ -795,54 +803,55 @@ static int matroxfb_set_par(struct fb_info *info)
795 default: mt.delay = 31 + 8; break; 803 default: mt.delay = 31 + 8; break;
796 } 804 }
797 805
798 hw = &ACCESS_FBINFO(hw); 806 hw = &minfo->hw;
799 807
800 down_read(&ACCESS_FBINFO(altout).lock); 808 down_read(&minfo->altout.lock);
801 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 809 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
802 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && 810 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
803 ACCESS_FBINFO(outputs[out]).output->compute) { 811 minfo->outputs[out].output->compute) {
804 ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt); 812 minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
805 } 813 }
806 } 814 }
807 up_read(&ACCESS_FBINFO(altout).lock); 815 up_read(&minfo->altout.lock);
808 ACCESS_FBINFO(crtc1).pixclock = mt.pixclock; 816 minfo->crtc1.pixclock = mt.pixclock;
809 ACCESS_FBINFO(crtc1).mnp = mt.mnp; 817 minfo->crtc1.mnp = mt.mnp;
810 ACCESS_FBINFO(hw_switch->init(PMINFO &mt)); 818 minfo->hw_switch->init(minfo, &mt);
811 pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; 819 pos = (var->yoffset * var->xres_virtual + var->xoffset) * minfo->curr.final_bppShift / 32;
812 pos += ACCESS_FBINFO(curr.ydstorg.chunks); 820 pos += minfo->curr.ydstorg.chunks;
813 821
814 hw->CRTC[0x0D] = pos & 0xFF; 822 hw->CRTC[0x0D] = pos & 0xFF;
815 hw->CRTC[0x0C] = (pos & 0xFF00) >> 8; 823 hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
816 hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); 824 hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
817 hw->CRTCEXT[8] = pos >> 21; 825 hw->CRTCEXT[8] = pos >> 21;
818 ACCESS_FBINFO(hw_switch->restore(PMINFO2)); 826 minfo->hw_switch->restore(minfo);
819 update_crtc2(PMINFO pos); 827 update_crtc2(minfo, pos);
820 down_read(&ACCESS_FBINFO(altout).lock); 828 down_read(&minfo->altout.lock);
821 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 829 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
822 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && 830 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
823 ACCESS_FBINFO(outputs[out]).output->program) { 831 minfo->outputs[out].output->program) {
824 ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data); 832 minfo->outputs[out].output->program(minfo->outputs[out].data);
825 } 833 }
826 } 834 }
827 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 835 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
828 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && 836 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
829 ACCESS_FBINFO(outputs[out]).output->start) { 837 minfo->outputs[out].output->start) {
830 ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data); 838 minfo->outputs[out].output->start(minfo->outputs[out].data);
831 } 839 }
832 } 840 }
833 up_read(&ACCESS_FBINFO(altout).lock); 841 up_read(&minfo->altout.lock);
834 matrox_cfbX_init(PMINFO2); 842 matrox_cfbX_init(minfo);
835 } 843 }
836 } 844 }
837 ACCESS_FBINFO(initialized) = 1; 845 minfo->initialized = 1;
838 return 0; 846 return 0;
839} 847}
840 848
841static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank) 849static int matroxfb_get_vblank(struct matrox_fb_info *minfo,
850 struct fb_vblank *vblank)
842{ 851{
843 unsigned int sts1; 852 unsigned int sts1;
844 853
845 matroxfb_enable_irq(PMINFO 0); 854 matroxfb_enable_irq(minfo, 0);
846 memset(vblank, 0, sizeof(*vblank)); 855 memset(vblank, 0, sizeof(*vblank));
847 vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC | 856 vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC |
848 FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK; 857 FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK;
@@ -855,13 +864,13 @@ static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank)
855 vblank->flags |= FB_VBLANK_HBLANKING; 864 vblank->flags |= FB_VBLANK_HBLANKING;
856 if (sts1 & 8) 865 if (sts1 & 8)
857 vblank->flags |= FB_VBLANK_VSYNCING; 866 vblank->flags |= FB_VBLANK_VSYNCING;
858 if (vblank->vcount >= ACCESS_FBINFO(fbcon).var.yres) 867 if (vblank->vcount >= minfo->fbcon.var.yres)
859 vblank->flags |= FB_VBLANK_VBLANKING; 868 vblank->flags |= FB_VBLANK_VBLANKING;
860 if (test_bit(0, &ACCESS_FBINFO(irq_flags))) { 869 if (test_bit(0, &minfo->irq_flags)) {
861 vblank->flags |= FB_VBLANK_HAVE_COUNT; 870 vblank->flags |= FB_VBLANK_HAVE_COUNT;
862 /* Only one writer, aligned int value... 871 /* Only one writer, aligned int value...
863 it should work without lock and without atomic_t */ 872 it should work without lock and without atomic_t */
864 vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt; 873 vblank->count = minfo->crtc1.vsync.cnt;
865 } 874 }
866 return 0; 875 return 0;
867} 876}
@@ -874,11 +883,11 @@ static int matroxfb_ioctl(struct fb_info *info,
874 unsigned int cmd, unsigned long arg) 883 unsigned int cmd, unsigned long arg)
875{ 884{
876 void __user *argp = (void __user *)arg; 885 void __user *argp = (void __user *)arg;
877 MINFO_FROM_INFO(info); 886 struct matrox_fb_info *minfo = info2minfo(info);
878 887
879 DBG(__func__) 888 DBG(__func__)
880 889
881 if (ACCESS_FBINFO(dead)) { 890 if (minfo->dead) {
882 return -ENXIO; 891 return -ENXIO;
883 } 892 }
884 893
@@ -888,7 +897,7 @@ static int matroxfb_ioctl(struct fb_info *info,
888 struct fb_vblank vblank; 897 struct fb_vblank vblank;
889 int err; 898 int err;
890 899
891 err = matroxfb_get_vblank(PMINFO &vblank); 900 err = matroxfb_get_vblank(minfo, &vblank);
892 if (err) 901 if (err)
893 return err; 902 return err;
894 if (copy_to_user(argp, &vblank, sizeof(vblank))) 903 if (copy_to_user(argp, &vblank, sizeof(vblank)))
@@ -902,7 +911,7 @@ static int matroxfb_ioctl(struct fb_info *info,
902 if (get_user(crt, (u_int32_t __user *)arg)) 911 if (get_user(crt, (u_int32_t __user *)arg))
903 return -EFAULT; 912 return -EFAULT;
904 913
905 return matroxfb_wait_for_sync(PMINFO crt); 914 return matroxfb_wait_for_sync(minfo, crt);
906 } 915 }
907 case MATROXFB_SET_OUTPUT_MODE: 916 case MATROXFB_SET_OUTPUT_MODE:
908 { 917 {
@@ -914,8 +923,8 @@ static int matroxfb_ioctl(struct fb_info *info,
914 return -EFAULT; 923 return -EFAULT;
915 if (mom.output >= MATROXFB_MAX_OUTPUTS) 924 if (mom.output >= MATROXFB_MAX_OUTPUTS)
916 return -ENXIO; 925 return -ENXIO;
917 down_read(&ACCESS_FBINFO(altout.lock)); 926 down_read(&minfo->altout.lock);
918 oproc = ACCESS_FBINFO(outputs[mom.output]).output; 927 oproc = minfo->outputs[mom.output].output;
919 if (!oproc) { 928 if (!oproc) {
920 val = -ENXIO; 929 val = -ENXIO;
921 } else if (!oproc->verifymode) { 930 } else if (!oproc->verifymode) {
@@ -925,18 +934,18 @@ static int matroxfb_ioctl(struct fb_info *info,
925 val = -EINVAL; 934 val = -EINVAL;
926 } 935 }
927 } else { 936 } else {
928 val = oproc->verifymode(ACCESS_FBINFO(outputs[mom.output]).data, mom.mode); 937 val = oproc->verifymode(minfo->outputs[mom.output].data, mom.mode);
929 } 938 }
930 if (!val) { 939 if (!val) {
931 if (ACCESS_FBINFO(outputs[mom.output]).mode != mom.mode) { 940 if (minfo->outputs[mom.output].mode != mom.mode) {
932 ACCESS_FBINFO(outputs[mom.output]).mode = mom.mode; 941 minfo->outputs[mom.output].mode = mom.mode;
933 val = 1; 942 val = 1;
934 } 943 }
935 } 944 }
936 up_read(&ACCESS_FBINFO(altout.lock)); 945 up_read(&minfo->altout.lock);
937 if (val != 1) 946 if (val != 1)
938 return val; 947 return val;
939 switch (ACCESS_FBINFO(outputs[mom.output]).src) { 948 switch (minfo->outputs[mom.output].src) {
940 case MATROXFB_SRC_CRTC1: 949 case MATROXFB_SRC_CRTC1:
941 matroxfb_set_par(info); 950 matroxfb_set_par(info);
942 break; 951 break;
@@ -944,11 +953,11 @@ static int matroxfb_ioctl(struct fb_info *info,
944 { 953 {
945 struct matroxfb_dh_fb_info* crtc2; 954 struct matroxfb_dh_fb_info* crtc2;
946 955
947 down_read(&ACCESS_FBINFO(crtc2.lock)); 956 down_read(&minfo->crtc2.lock);
948 crtc2 = ACCESS_FBINFO(crtc2.info); 957 crtc2 = minfo->crtc2.info;
949 if (crtc2) 958 if (crtc2)
950 crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon); 959 crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon);
951 up_read(&ACCESS_FBINFO(crtc2.lock)); 960 up_read(&minfo->crtc2.lock);
952 } 961 }
953 break; 962 break;
954 } 963 }
@@ -964,15 +973,15 @@ static int matroxfb_ioctl(struct fb_info *info,
964 return -EFAULT; 973 return -EFAULT;
965 if (mom.output >= MATROXFB_MAX_OUTPUTS) 974 if (mom.output >= MATROXFB_MAX_OUTPUTS)
966 return -ENXIO; 975 return -ENXIO;
967 down_read(&ACCESS_FBINFO(altout.lock)); 976 down_read(&minfo->altout.lock);
968 oproc = ACCESS_FBINFO(outputs[mom.output]).output; 977 oproc = minfo->outputs[mom.output].output;
969 if (!oproc) { 978 if (!oproc) {
970 val = -ENXIO; 979 val = -ENXIO;
971 } else { 980 } else {
972 mom.mode = ACCESS_FBINFO(outputs[mom.output]).mode; 981 mom.mode = minfo->outputs[mom.output].mode;
973 val = 0; 982 val = 0;
974 } 983 }
975 up_read(&ACCESS_FBINFO(altout.lock)); 984 up_read(&minfo->altout.lock);
976 if (val) 985 if (val)
977 return val; 986 return val;
978 if (copy_to_user(argp, &mom, sizeof(mom))) 987 if (copy_to_user(argp, &mom, sizeof(mom)))
@@ -991,9 +1000,9 @@ static int matroxfb_ioctl(struct fb_info *info,
991 if (tmp & (1 << i)) { 1000 if (tmp & (1 << i)) {
992 if (i >= MATROXFB_MAX_OUTPUTS) 1001 if (i >= MATROXFB_MAX_OUTPUTS)
993 return -ENXIO; 1002 return -ENXIO;
994 if (!ACCESS_FBINFO(outputs[i]).output) 1003 if (!minfo->outputs[i].output)
995 return -ENXIO; 1004 return -ENXIO;
996 switch (ACCESS_FBINFO(outputs[i]).src) { 1005 switch (minfo->outputs[i].src) {
997 case MATROXFB_SRC_NONE: 1006 case MATROXFB_SRC_NONE:
998 case MATROXFB_SRC_CRTC1: 1007 case MATROXFB_SRC_CRTC1:
999 break; 1008 break;
@@ -1002,12 +1011,12 @@ static int matroxfb_ioctl(struct fb_info *info,
1002 } 1011 }
1003 } 1012 }
1004 } 1013 }
1005 if (ACCESS_FBINFO(devflags.panellink)) { 1014 if (minfo->devflags.panellink) {
1006 if (tmp & MATROXFB_OUTPUT_CONN_DFP) { 1015 if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
1007 if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY) 1016 if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
1008 return -EINVAL; 1017 return -EINVAL;
1009 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { 1018 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1010 if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC2) { 1019 if (minfo->outputs[i].src == MATROXFB_SRC_CRTC2) {
1011 return -EBUSY; 1020 return -EBUSY;
1012 } 1021 }
1013 } 1022 }
@@ -1016,13 +1025,13 @@ static int matroxfb_ioctl(struct fb_info *info,
1016 changes = 0; 1025 changes = 0;
1017 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { 1026 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1018 if (tmp & (1 << i)) { 1027 if (tmp & (1 << i)) {
1019 if (ACCESS_FBINFO(outputs[i]).src != MATROXFB_SRC_CRTC1) { 1028 if (minfo->outputs[i].src != MATROXFB_SRC_CRTC1) {
1020 changes = 1; 1029 changes = 1;
1021 ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_CRTC1; 1030 minfo->outputs[i].src = MATROXFB_SRC_CRTC1;
1022 } 1031 }
1023 } else if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) { 1032 } else if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
1024 changes = 1; 1033 changes = 1;
1025 ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_NONE; 1034 minfo->outputs[i].src = MATROXFB_SRC_NONE;
1026 } 1035 }
1027 } 1036 }
1028 if (!changes) 1037 if (!changes)
@@ -1036,7 +1045,7 @@ static int matroxfb_ioctl(struct fb_info *info,
1036 int i; 1045 int i;
1037 1046
1038 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { 1047 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1039 if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) { 1048 if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
1040 conn |= 1 << i; 1049 conn |= 1 << i;
1041 } 1050 }
1042 } 1051 }
@@ -1050,8 +1059,8 @@ static int matroxfb_ioctl(struct fb_info *info,
1050 int i; 1059 int i;
1051 1060
1052 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { 1061 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1053 if (ACCESS_FBINFO(outputs[i]).output) { 1062 if (minfo->outputs[i].output) {
1054 switch (ACCESS_FBINFO(outputs[i]).src) { 1063 switch (minfo->outputs[i].src) {
1055 case MATROXFB_SRC_NONE: 1064 case MATROXFB_SRC_NONE:
1056 case MATROXFB_SRC_CRTC1: 1065 case MATROXFB_SRC_CRTC1:
1057 conn |= 1 << i; 1066 conn |= 1 << i;
@@ -1059,7 +1068,7 @@ static int matroxfb_ioctl(struct fb_info *info,
1059 } 1068 }
1060 } 1069 }
1061 } 1070 }
1062 if (ACCESS_FBINFO(devflags.panellink)) { 1071 if (minfo->devflags.panellink) {
1063 if (conn & MATROXFB_OUTPUT_CONN_DFP) 1072 if (conn & MATROXFB_OUTPUT_CONN_DFP)
1064 conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY; 1073 conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
1065 if (conn & MATROXFB_OUTPUT_CONN_SECONDARY) 1074 if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
@@ -1075,7 +1084,7 @@ static int matroxfb_ioctl(struct fb_info *info,
1075 int i; 1084 int i;
1076 1085
1077 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { 1086 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1078 if (ACCESS_FBINFO(outputs[i]).output) { 1087 if (minfo->outputs[i].output) {
1079 conn |= 1 << i; 1088 conn |= 1 << i;
1080 } 1089 }
1081 } 1090 }
@@ -1090,7 +1099,7 @@ static int matroxfb_ioctl(struct fb_info *info,
1090 memset(&r, 0, sizeof(r)); 1099 memset(&r, 0, sizeof(r));
1091 strcpy(r.driver, "matroxfb"); 1100 strcpy(r.driver, "matroxfb");
1092 strcpy(r.card, "Matrox"); 1101 strcpy(r.card, "Matrox");
1093 sprintf(r.bus_info, "PCI:%s", pci_name(ACCESS_FBINFO(pcidev))); 1102 sprintf(r.bus_info, "PCI:%s", pci_name(minfo->pcidev));
1094 r.version = KERNEL_VERSION(1,0,0); 1103 r.version = KERNEL_VERSION(1,0,0);
1095 r.capabilities = V4L2_CAP_VIDEO_OUTPUT; 1104 r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
1096 if (copy_to_user(argp, &r, sizeof(r))) 1105 if (copy_to_user(argp, &r, sizeof(r)))
@@ -1106,15 +1115,15 @@ static int matroxfb_ioctl(struct fb_info *info,
1106 if (copy_from_user(&qctrl, argp, sizeof(qctrl))) 1115 if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
1107 return -EFAULT; 1116 return -EFAULT;
1108 1117
1109 down_read(&ACCESS_FBINFO(altout).lock); 1118 down_read(&minfo->altout.lock);
1110 if (!ACCESS_FBINFO(outputs[1]).output) { 1119 if (!minfo->outputs[1].output) {
1111 err = -ENXIO; 1120 err = -ENXIO;
1112 } else if (ACCESS_FBINFO(outputs[1]).output->getqueryctrl) { 1121 } else if (minfo->outputs[1].output->getqueryctrl) {
1113 err = ACCESS_FBINFO(outputs[1]).output->getqueryctrl(ACCESS_FBINFO(outputs[1]).data, &qctrl); 1122 err = minfo->outputs[1].output->getqueryctrl(minfo->outputs[1].data, &qctrl);
1114 } else { 1123 } else {
1115 err = -EINVAL; 1124 err = -EINVAL;
1116 } 1125 }
1117 up_read(&ACCESS_FBINFO(altout).lock); 1126 up_read(&minfo->altout.lock);
1118 if (err >= 0 && 1127 if (err >= 0 &&
1119 copy_to_user(argp, &qctrl, sizeof(qctrl))) 1128 copy_to_user(argp, &qctrl, sizeof(qctrl)))
1120 return -EFAULT; 1129 return -EFAULT;
@@ -1128,15 +1137,15 @@ static int matroxfb_ioctl(struct fb_info *info,
1128 if (copy_from_user(&ctrl, argp, sizeof(ctrl))) 1137 if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
1129 return -EFAULT; 1138 return -EFAULT;
1130 1139
1131 down_read(&ACCESS_FBINFO(altout).lock); 1140 down_read(&minfo->altout.lock);
1132 if (!ACCESS_FBINFO(outputs[1]).output) { 1141 if (!minfo->outputs[1].output) {
1133 err = -ENXIO; 1142 err = -ENXIO;
1134 } else if (ACCESS_FBINFO(outputs[1]).output->getctrl) { 1143 } else if (minfo->outputs[1].output->getctrl) {
1135 err = ACCESS_FBINFO(outputs[1]).output->getctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl); 1144 err = minfo->outputs[1].output->getctrl(minfo->outputs[1].data, &ctrl);
1136 } else { 1145 } else {
1137 err = -EINVAL; 1146 err = -EINVAL;
1138 } 1147 }
1139 up_read(&ACCESS_FBINFO(altout).lock); 1148 up_read(&minfo->altout.lock);
1140 if (err >= 0 && 1149 if (err >= 0 &&
1141 copy_to_user(argp, &ctrl, sizeof(ctrl))) 1150 copy_to_user(argp, &ctrl, sizeof(ctrl)))
1142 return -EFAULT; 1151 return -EFAULT;
@@ -1151,15 +1160,15 @@ static int matroxfb_ioctl(struct fb_info *info,
1151 if (copy_from_user(&ctrl, argp, sizeof(ctrl))) 1160 if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
1152 return -EFAULT; 1161 return -EFAULT;
1153 1162
1154 down_read(&ACCESS_FBINFO(altout).lock); 1163 down_read(&minfo->altout.lock);
1155 if (!ACCESS_FBINFO(outputs[1]).output) { 1164 if (!minfo->outputs[1].output) {
1156 err = -ENXIO; 1165 err = -ENXIO;
1157 } else if (ACCESS_FBINFO(outputs[1]).output->setctrl) { 1166 } else if (minfo->outputs[1].output->setctrl) {
1158 err = ACCESS_FBINFO(outputs[1]).output->setctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl); 1167 err = minfo->outputs[1].output->setctrl(minfo->outputs[1].data, &ctrl);
1159 } else { 1168 } else {
1160 err = -EINVAL; 1169 err = -EINVAL;
1161 } 1170 }
1162 up_read(&ACCESS_FBINFO(altout).lock); 1171 up_read(&minfo->altout.lock);
1163 return err; 1172 return err;
1164 } 1173 }
1165 } 1174 }
@@ -1173,11 +1182,11 @@ static int matroxfb_blank(int blank, struct fb_info *info)
1173 int seq; 1182 int seq;
1174 int crtc; 1183 int crtc;
1175 CRITFLAGS 1184 CRITFLAGS
1176 MINFO_FROM_INFO(info); 1185 struct matrox_fb_info *minfo = info2minfo(info);
1177 1186
1178 DBG(__func__) 1187 DBG(__func__)
1179 1188
1180 if (ACCESS_FBINFO(dead)) 1189 if (minfo->dead)
1181 return 1; 1190 return 1;
1182 1191
1183 switch (blank) { 1192 switch (blank) {
@@ -1279,7 +1288,9 @@ static char outputs[8]; /* "matrox:outputs:xxx" */
1279static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */ 1288static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */
1280#endif 1289#endif
1281 1290
1282static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSize){ 1291static int matroxfb_getmemory(struct matrox_fb_info *minfo,
1292 unsigned int maxSize, unsigned int *realSize)
1293{
1283 vaddr_t vm; 1294 vaddr_t vm;
1284 unsigned int offs; 1295 unsigned int offs;
1285 unsigned int offs2; 1296 unsigned int offs2;
@@ -1289,7 +1300,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
1289 1300
1290 DBG(__func__) 1301 DBG(__func__)
1291 1302
1292 vm = ACCESS_FBINFO(video.vbase); 1303 vm = minfo->video.vbase;
1293 maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */ 1304 maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
1294 /* at least 2MB */ 1305 /* at least 2MB */
1295 if (maxSize < 0x0200000) return 0; 1306 if (maxSize < 0x0200000) return 0;
@@ -1321,7 +1332,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
1321 1332
1322 *realSize = offs - 0x100000; 1333 *realSize = offs - 0x100000;
1323#ifdef CONFIG_FB_MATROX_MILLENIUM 1334#ifdef CONFIG_FB_MATROX_MILLENIUM
1324 ACCESS_FBINFO(interleave) = !(!isMillenium(MINFO) || ((offs - 0x100000) & 0x3FFFFF)); 1335 minfo->interleave = !(!isMillenium(minfo) || ((offs - 0x100000) & 0x3FFFFF));
1325#endif 1336#endif
1326 return 1; 1337 return 1;
1327} 1338}
@@ -1343,13 +1354,9 @@ static struct video_board vbMystique = {0x0800000, 0x0800000, FB_ACCEL_MATROX_M
1343#ifdef CONFIG_FB_MATROX_G 1354#ifdef CONFIG_FB_MATROX_G
1344static struct video_board vbG100 = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100}; 1355static struct video_board vbG100 = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100};
1345static struct video_board vbG200 = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100}; 1356static struct video_board vbG200 = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100};
1346#ifdef CONFIG_FB_MATROX_32MB
1347/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for 1357/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
1348 whole 32MB */ 1358 whole 32MB */
1349static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100}; 1359static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100};
1350#else
1351static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100};
1352#endif
1353#endif 1360#endif
1354 1361
1355#define DEVF_VIDEO64BIT 0x0001 1362#define DEVF_VIDEO64BIT 0x0001
@@ -1556,16 +1563,17 @@ static struct fb_videomode defaultmode = {
1556 1563
1557static int hotplug = 0; 1564static int hotplug = 0;
1558 1565
1559static void setDefaultOutputs(WPMINFO2) { 1566static void setDefaultOutputs(struct matrox_fb_info *minfo)
1567{
1560 unsigned int i; 1568 unsigned int i;
1561 const char* ptr; 1569 const char* ptr;
1562 1570
1563 ACCESS_FBINFO(outputs[0]).default_src = MATROXFB_SRC_CRTC1; 1571 minfo->outputs[0].default_src = MATROXFB_SRC_CRTC1;
1564 if (ACCESS_FBINFO(devflags.g450dac)) { 1572 if (minfo->devflags.g450dac) {
1565 ACCESS_FBINFO(outputs[1]).default_src = MATROXFB_SRC_CRTC1; 1573 minfo->outputs[1].default_src = MATROXFB_SRC_CRTC1;
1566 ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1; 1574 minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
1567 } else if (dfp) { 1575 } else if (dfp) {
1568 ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1; 1576 minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
1569 } 1577 }
1570 ptr = outputs; 1578 ptr = outputs;
1571 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { 1579 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
@@ -1575,11 +1583,11 @@ static void setDefaultOutputs(WPMINFO2) {
1575 break; 1583 break;
1576 } 1584 }
1577 if (c == '0') { 1585 if (c == '0') {
1578 ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_NONE; 1586 minfo->outputs[i].default_src = MATROXFB_SRC_NONE;
1579 } else if (c == '1') { 1587 } else if (c == '1') {
1580 ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC1; 1588 minfo->outputs[i].default_src = MATROXFB_SRC_CRTC1;
1581 } else if (c == '2' && ACCESS_FBINFO(devflags.crtc2)) { 1589 } else if (c == '2' && minfo->devflags.crtc2) {
1582 ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC2; 1590 minfo->outputs[i].default_src = MATROXFB_SRC_CRTC2;
1583 } else { 1591 } else {
1584 printk(KERN_ERR "matroxfb: Unknown outputs setting\n"); 1592 printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
1585 break; 1593 break;
@@ -1589,7 +1597,8 @@ static void setDefaultOutputs(WPMINFO2) {
1589 outputs[0] = 0; 1597 outputs[0] = 0;
1590} 1598}
1591 1599
1592static int initMatrox2(WPMINFO struct board* b){ 1600static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
1601{
1593 unsigned long ctrlptr_phys = 0; 1602 unsigned long ctrlptr_phys = 0;
1594 unsigned long video_base_phys = 0; 1603 unsigned long video_base_phys = 0;
1595 unsigned int memsize; 1604 unsigned int memsize;
@@ -1605,58 +1614,56 @@ static int initMatrox2(WPMINFO struct board* b){
1605 /* set default values... */ 1614 /* set default values... */
1606 vesafb_defined.accel_flags = FB_ACCELF_TEXT; 1615 vesafb_defined.accel_flags = FB_ACCELF_TEXT;
1607 1616
1608 ACCESS_FBINFO(hw_switch) = b->base->lowlevel; 1617 minfo->hw_switch = b->base->lowlevel;
1609 ACCESS_FBINFO(devflags.accelerator) = b->base->accelID; 1618 minfo->devflags.accelerator = b->base->accelID;
1610 ACCESS_FBINFO(max_pixel_clock) = b->maxclk; 1619 minfo->max_pixel_clock = b->maxclk;
1611 1620
1612 printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name); 1621 printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
1613 ACCESS_FBINFO(capable.plnwt) = 1; 1622 minfo->capable.plnwt = 1;
1614 ACCESS_FBINFO(chip) = b->chip; 1623 minfo->chip = b->chip;
1615 ACCESS_FBINFO(capable.srcorg) = b->flags & DEVF_SRCORG; 1624 minfo->capable.srcorg = b->flags & DEVF_SRCORG;
1616 ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT; 1625 minfo->devflags.video64bits = b->flags & DEVF_VIDEO64BIT;
1617 if (b->flags & DEVF_TEXT4B) { 1626 if (b->flags & DEVF_TEXT4B) {
1618 ACCESS_FBINFO(devflags.vgastep) = 4; 1627 minfo->devflags.vgastep = 4;
1619 ACCESS_FBINFO(devflags.textmode) = 4; 1628 minfo->devflags.textmode = 4;
1620 ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16; 1629 minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
1621 } else if (b->flags & DEVF_TEXT16B) { 1630 } else if (b->flags & DEVF_TEXT16B) {
1622 ACCESS_FBINFO(devflags.vgastep) = 16; 1631 minfo->devflags.vgastep = 16;
1623 ACCESS_FBINFO(devflags.textmode) = 1; 1632 minfo->devflags.textmode = 1;
1624 ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16; 1633 minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
1625 } else { 1634 } else {
1626 ACCESS_FBINFO(devflags.vgastep) = 8; 1635 minfo->devflags.vgastep = 8;
1627 ACCESS_FBINFO(devflags.textmode) = 1; 1636 minfo->devflags.textmode = 1;
1628 ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8; 1637 minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP8;
1629 } 1638 }
1630#ifdef CONFIG_FB_MATROX_32MB 1639 minfo->devflags.support32MB = (b->flags & DEVF_SUPPORT32MB) != 0;
1631 ACCESS_FBINFO(devflags.support32MB) = (b->flags & DEVF_SUPPORT32MB) != 0; 1640 minfo->devflags.precise_width = !(b->flags & DEVF_ANY_VXRES);
1632#endif 1641 minfo->devflags.crtc2 = (b->flags & DEVF_CRTC2) != 0;
1633 ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES); 1642 minfo->devflags.maven_capable = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
1634 ACCESS_FBINFO(devflags.crtc2) = (b->flags & DEVF_CRTC2) != 0; 1643 minfo->devflags.dualhead = (b->flags & DEVF_DUALHEAD) != 0;
1635 ACCESS_FBINFO(devflags.maven_capable) = (b->flags & DEVF_MAVEN_CAPABLE) != 0; 1644 minfo->devflags.dfp_type = dfp_type;
1636 ACCESS_FBINFO(devflags.dualhead) = (b->flags & DEVF_DUALHEAD) != 0; 1645 minfo->devflags.g450dac = (b->flags & DEVF_G450DAC) != 0;
1637 ACCESS_FBINFO(devflags.dfp_type) = dfp_type; 1646 minfo->devflags.textstep = minfo->devflags.vgastep * minfo->devflags.textmode;
1638 ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0; 1647 minfo->devflags.textvram = 65536 / minfo->devflags.textmode;
1639 ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); 1648 setDefaultOutputs(minfo);
1640 ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
1641 setDefaultOutputs(PMINFO2);
1642 if (b->flags & DEVF_PANELLINK_CAPABLE) { 1649 if (b->flags & DEVF_PANELLINK_CAPABLE) {
1643 ACCESS_FBINFO(outputs[2]).data = MINFO; 1650 minfo->outputs[2].data = minfo;
1644 ACCESS_FBINFO(outputs[2]).output = &panellink_output; 1651 minfo->outputs[2].output = &panellink_output;
1645 ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src; 1652 minfo->outputs[2].src = minfo->outputs[2].default_src;
1646 ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 1653 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
1647 ACCESS_FBINFO(devflags.panellink) = 1; 1654 minfo->devflags.panellink = 1;
1648 } 1655 }
1649 1656
1650 if (ACCESS_FBINFO(capable.cross4MB) < 0) 1657 if (minfo->capable.cross4MB < 0)
1651 ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB; 1658 minfo->capable.cross4MB = b->flags & DEVF_CROSS4MB;
1652 if (b->flags & DEVF_SWAPS) { 1659 if (b->flags & DEVF_SWAPS) {
1653 ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); 1660 ctrlptr_phys = pci_resource_start(minfo->pcidev, 1);
1654 video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); 1661 video_base_phys = pci_resource_start(minfo->pcidev, 0);
1655 ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_0; 1662 minfo->devflags.fbResource = PCI_BASE_ADDRESS_0;
1656 } else { 1663 } else {
1657 ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); 1664 ctrlptr_phys = pci_resource_start(minfo->pcidev, 0);
1658 video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); 1665 video_base_phys = pci_resource_start(minfo->pcidev, 1);
1659 ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_1; 1666 minfo->devflags.fbResource = PCI_BASE_ADDRESS_1;
1660 } 1667 }
1661 err = -EINVAL; 1668 err = -EINVAL;
1662 if (!ctrlptr_phys) { 1669 if (!ctrlptr_phys) {
@@ -1674,7 +1681,7 @@ static int initMatrox2(WPMINFO struct board* b){
1674 if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) { 1681 if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
1675 goto failCtrlMR; 1682 goto failCtrlMR;
1676 } 1683 }
1677 ACCESS_FBINFO(video.len_maximum) = memsize; 1684 minfo->video.len_maximum = memsize;
1678 /* convert mem (autodetect k, M) */ 1685 /* convert mem (autodetect k, M) */
1679 if (mem < 1024) mem *= 1024; 1686 if (mem < 1024) mem *= 1024;
1680 if (mem < 0x00100000) mem *= 1024; 1687 if (mem < 0x00100000) mem *= 1024;
@@ -1682,14 +1689,14 @@ static int initMatrox2(WPMINFO struct board* b){
1682 if (mem && (mem < memsize)) 1689 if (mem && (mem < memsize))
1683 memsize = mem; 1690 memsize = mem;
1684 err = -ENOMEM; 1691 err = -ENOMEM;
1685 if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &ACCESS_FBINFO(mmio.vbase))) { 1692 if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &minfo->mmio.vbase)) {
1686 printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys); 1693 printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
1687 goto failVideoMR; 1694 goto failVideoMR;
1688 } 1695 }
1689 ACCESS_FBINFO(mmio.base) = ctrlptr_phys; 1696 minfo->mmio.base = ctrlptr_phys;
1690 ACCESS_FBINFO(mmio.len) = 16384; 1697 minfo->mmio.len = 16384;
1691 ACCESS_FBINFO(video.base) = video_base_phys; 1698 minfo->video.base = video_base_phys;
1692 if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) { 1699 if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &minfo->video.vbase)) {
1693 printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n", 1700 printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
1694 video_base_phys, memsize); 1701 video_base_phys, memsize);
1695 goto failCtrlIO; 1702 goto failCtrlIO;
@@ -1698,63 +1705,63 @@ static int initMatrox2(WPMINFO struct board* b){
1698 u_int32_t cmd; 1705 u_int32_t cmd;
1699 u_int32_t mga_option; 1706 u_int32_t mga_option;
1700 1707
1701 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &mga_option); 1708 pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &mga_option);
1702 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd); 1709 pci_read_config_dword(minfo->pcidev, PCI_COMMAND, &cmd);
1703 mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */ 1710 mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
1704 mga_option |= MX_OPTION_BSWAP; 1711 mga_option |= MX_OPTION_BSWAP;
1705 /* disable palette snooping */ 1712 /* disable palette snooping */
1706 cmd &= ~PCI_COMMAND_VGA_PALETTE; 1713 cmd &= ~PCI_COMMAND_VGA_PALETTE;
1707 if (pci_dev_present(intel_82437)) { 1714 if (pci_dev_present(intel_82437)) {
1708 if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) { 1715 if (!(mga_option & 0x20000000) && !minfo->devflags.nopciretry) {
1709 printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n"); 1716 printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
1710 } 1717 }
1711 mga_option |= 0x20000000; 1718 mga_option |= 0x20000000;
1712 ACCESS_FBINFO(devflags.nopciretry) = 1; 1719 minfo->devflags.nopciretry = 1;
1713 } 1720 }
1714 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, cmd); 1721 pci_write_config_dword(minfo->pcidev, PCI_COMMAND, cmd);
1715 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mga_option); 1722 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mga_option);
1716 ACCESS_FBINFO(hw).MXoptionReg = mga_option; 1723 minfo->hw.MXoptionReg = mga_option;
1717 1724
1718 /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */ 1725 /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
1719 /* maybe preinit() candidate, but it is same... for all devices... at this time... */ 1726 /* maybe preinit() candidate, but it is same... for all devices... at this time... */
1720 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MGA_INDEX, 0x00003C00); 1727 pci_write_config_dword(minfo->pcidev, PCI_MGA_INDEX, 0x00003C00);
1721 } 1728 }
1722 1729
1723 err = -ENXIO; 1730 err = -ENXIO;
1724 matroxfb_read_pins(PMINFO2); 1731 matroxfb_read_pins(minfo);
1725 if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO2)) { 1732 if (minfo->hw_switch->preinit(minfo)) {
1726 goto failVideoIO; 1733 goto failVideoIO;
1727 } 1734 }
1728 1735
1729 err = -ENOMEM; 1736 err = -ENOMEM;
1730 if (!matroxfb_getmemory(PMINFO memsize, &ACCESS_FBINFO(video.len)) || !ACCESS_FBINFO(video.len)) { 1737 if (!matroxfb_getmemory(minfo, memsize, &minfo->video.len) || !minfo->video.len) {
1731 printk(KERN_ERR "matroxfb: cannot determine memory size\n"); 1738 printk(KERN_ERR "matroxfb: cannot determine memory size\n");
1732 goto failVideoIO; 1739 goto failVideoIO;
1733 } 1740 }
1734 ACCESS_FBINFO(devflags.ydstorg) = 0; 1741 minfo->devflags.ydstorg = 0;
1735 1742
1736 ACCESS_FBINFO(video.base) = video_base_phys; 1743 minfo->video.base = video_base_phys;
1737 ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len); 1744 minfo->video.len_usable = minfo->video.len;
1738 if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable) 1745 if (minfo->video.len_usable > b->base->maxdisplayable)
1739 ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable; 1746 minfo->video.len_usable = b->base->maxdisplayable;
1740#ifdef CONFIG_MTRR 1747#ifdef CONFIG_MTRR
1741 if (mtrr) { 1748 if (mtrr) {
1742 ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1); 1749 minfo->mtrr.vram = mtrr_add(video_base_phys, minfo->video.len, MTRR_TYPE_WRCOMB, 1);
1743 ACCESS_FBINFO(mtrr.vram_valid) = 1; 1750 minfo->mtrr.vram_valid = 1;
1744 printk(KERN_INFO "matroxfb: MTRR's turned on\n"); 1751 printk(KERN_INFO "matroxfb: MTRR's turned on\n");
1745 } 1752 }
1746#endif /* CONFIG_MTRR */ 1753#endif /* CONFIG_MTRR */
1747 1754
1748 if (!ACCESS_FBINFO(devflags.novga)) 1755 if (!minfo->devflags.novga)
1749 request_region(0x3C0, 32, "matrox"); 1756 request_region(0x3C0, 32, "matrox");
1750 matroxfb_g450_connect(PMINFO2); 1757 matroxfb_g450_connect(minfo);
1751 ACCESS_FBINFO(hw_switch->reset(PMINFO2)); 1758 minfo->hw_switch->reset(minfo);
1752 1759
1753 ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0; 1760 minfo->fbcon.monspecs.hfmin = 0;
1754 ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh; 1761 minfo->fbcon.monspecs.hfmax = fh;
1755 ACCESS_FBINFO(fbcon.monspecs.vfmin) = 0; 1762 minfo->fbcon.monspecs.vfmin = 0;
1756 ACCESS_FBINFO(fbcon.monspecs.vfmax) = fv; 1763 minfo->fbcon.monspecs.vfmax = fv;
1757 ACCESS_FBINFO(fbcon.monspecs.dpms) = 0; /* TBD */ 1764 minfo->fbcon.monspecs.dpms = 0; /* TBD */
1758 1765
1759 /* static settings */ 1766 /* static settings */
1760 vesafb_defined.red = colors[depth-1].red; 1767 vesafb_defined.red = colors[depth-1].red;
@@ -1766,24 +1773,24 @@ static int initMatrox2(WPMINFO struct board* b){
1766 if (noaccel) 1773 if (noaccel)
1767 vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT; 1774 vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
1768 1775
1769 ACCESS_FBINFO(fbops) = matroxfb_ops; 1776 minfo->fbops = matroxfb_ops;
1770 ACCESS_FBINFO(fbcon.fbops) = &ACCESS_FBINFO(fbops); 1777 minfo->fbcon.fbops = &minfo->fbops;
1771 ACCESS_FBINFO(fbcon.pseudo_palette) = ACCESS_FBINFO(cmap); 1778 minfo->fbcon.pseudo_palette = minfo->cmap;
1772 /* after __init time we are like module... no logo */ 1779 /* after __init time we are like module... no logo */
1773 ACCESS_FBINFO(fbcon.flags) = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT; 1780 minfo->fbcon.flags = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT;
1774 ACCESS_FBINFO(fbcon.flags) |= FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */ 1781 minfo->fbcon.flags |= FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */
1775 FBINFO_HWACCEL_COPYAREA | /* We have hw-assisted bmove */ 1782 FBINFO_HWACCEL_COPYAREA | /* We have hw-assisted bmove */
1776 FBINFO_HWACCEL_FILLRECT | /* And fillrect */ 1783 FBINFO_HWACCEL_FILLRECT | /* And fillrect */
1777 FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */ 1784 FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
1778 FBINFO_HWACCEL_XPAN | /* And we support both horizontal */ 1785 FBINFO_HWACCEL_XPAN | /* And we support both horizontal */
1779 FBINFO_HWACCEL_YPAN; /* And vertical panning */ 1786 FBINFO_HWACCEL_YPAN; /* And vertical panning */
1780 ACCESS_FBINFO(video.len_usable) &= PAGE_MASK; 1787 minfo->video.len_usable &= PAGE_MASK;
1781 fb_alloc_cmap(&ACCESS_FBINFO(fbcon.cmap), 256, 1); 1788 fb_alloc_cmap(&minfo->fbcon.cmap, 256, 1);
1782 1789
1783#ifndef MODULE 1790#ifndef MODULE
1784 /* mode database is marked __init!!! */ 1791 /* mode database is marked __init!!! */
1785 if (!hotplug) { 1792 if (!hotplug) {
1786 fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL, 1793 fb_find_mode(&vesafb_defined, &minfo->fbcon, videomode[0] ? videomode : NULL,
1787 NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel); 1794 NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
1788 } 1795 }
1789#endif /* !MODULE */ 1796#endif /* !MODULE */
@@ -1872,53 +1879,52 @@ static int initMatrox2(WPMINFO struct board* b){
1872 vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough 1879 vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
1873 to yres_virtual * xres_virtual < 2^32 */ 1880 to yres_virtual * xres_virtual < 2^32 */
1874 } 1881 }
1875 matroxfb_init_fix(PMINFO2); 1882 matroxfb_init_fix(minfo);
1876 ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); 1883 minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase);
1877 matroxfb_update_fix(PMINFO2);
1878 /* Normalize values (namely yres_virtual) */ 1884 /* Normalize values (namely yres_virtual) */
1879 matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); 1885 matroxfb_check_var(&vesafb_defined, &minfo->fbcon);
1880 /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over 1886 /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
1881 * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var, 1887 * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
1882 * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work 1888 * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
1883 * anyway. But we at least tried... */ 1889 * anyway. But we at least tried... */
1884 ACCESS_FBINFO(fbcon.var) = vesafb_defined; 1890 minfo->fbcon.var = vesafb_defined;
1885 err = -EINVAL; 1891 err = -EINVAL;
1886 1892
1887 printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n", 1893 printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
1888 vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, 1894 vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
1889 vesafb_defined.xres_virtual, vesafb_defined.yres_virtual); 1895 vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
1890 printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n", 1896 printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
1891 ACCESS_FBINFO(video.base), vaddr_va(ACCESS_FBINFO(video.vbase)), ACCESS_FBINFO(video.len)); 1897 minfo->video.base, vaddr_va(minfo->video.vbase), minfo->video.len);
1892 1898
1893/* We do not have to set currcon to 0... register_framebuffer do it for us on first console 1899/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
1894 * and we do not want currcon == 0 for subsequent framebuffers */ 1900 * and we do not want currcon == 0 for subsequent framebuffers */
1895 1901
1896 ACCESS_FBINFO(fbcon).device = &ACCESS_FBINFO(pcidev)->dev; 1902 minfo->fbcon.device = &minfo->pcidev->dev;
1897 if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) { 1903 if (register_framebuffer(&minfo->fbcon) < 0) {
1898 goto failVideoIO; 1904 goto failVideoIO;
1899 } 1905 }
1900 printk("fb%d: %s frame buffer device\n", 1906 printk("fb%d: %s frame buffer device\n",
1901 ACCESS_FBINFO(fbcon.node), ACCESS_FBINFO(fbcon.fix.id)); 1907 minfo->fbcon.node, minfo->fbcon.fix.id);
1902 1908
1903 /* there is no console on this fb... but we have to initialize hardware 1909 /* there is no console on this fb... but we have to initialize hardware
1904 * until someone tells me what is proper thing to do */ 1910 * until someone tells me what is proper thing to do */
1905 if (!ACCESS_FBINFO(initialized)) { 1911 if (!minfo->initialized) {
1906 printk(KERN_INFO "fb%d: initializing hardware\n", 1912 printk(KERN_INFO "fb%d: initializing hardware\n",
1907 ACCESS_FBINFO(fbcon.node)); 1913 minfo->fbcon.node);
1908 /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var 1914 /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
1909 * already before, so register_framebuffer works correctly. */ 1915 * already before, so register_framebuffer works correctly. */
1910 vesafb_defined.activate |= FB_ACTIVATE_FORCE; 1916 vesafb_defined.activate |= FB_ACTIVATE_FORCE;
1911 fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined); 1917 fb_set_var(&minfo->fbcon, &vesafb_defined);
1912 } 1918 }
1913 1919
1914 return 0; 1920 return 0;
1915failVideoIO:; 1921failVideoIO:;
1916 matroxfb_g450_shutdown(PMINFO2); 1922 matroxfb_g450_shutdown(minfo);
1917 mga_iounmap(ACCESS_FBINFO(video.vbase)); 1923 mga_iounmap(minfo->video.vbase);
1918failCtrlIO:; 1924failCtrlIO:;
1919 mga_iounmap(ACCESS_FBINFO(mmio.vbase)); 1925 mga_iounmap(minfo->mmio.vbase);
1920failVideoMR:; 1926failVideoMR:;
1921 release_mem_region(video_base_phys, ACCESS_FBINFO(video.len_maximum)); 1927 release_mem_region(video_base_phys, minfo->video.len_maximum);
1922failCtrlMR:; 1928failCtrlMR:;
1923 release_mem_region(ctrlptr_phys, 16384); 1929 release_mem_region(ctrlptr_phys, 16384);
1924fail:; 1930fail:;
@@ -1974,7 +1980,7 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv) {
1974static void matroxfb_register_device(struct matrox_fb_info* minfo) { 1980static void matroxfb_register_device(struct matrox_fb_info* minfo) {
1975 struct matroxfb_driver* drv; 1981 struct matroxfb_driver* drv;
1976 int i = 0; 1982 int i = 0;
1977 list_add(&ACCESS_FBINFO(next_fb), &matroxfb_list); 1983 list_add(&minfo->next_fb, &matroxfb_list);
1978 for (drv = matroxfb_driver_l(matroxfb_driver_list.next); 1984 for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
1979 drv != matroxfb_driver_l(&matroxfb_driver_list); 1985 drv != matroxfb_driver_l(&matroxfb_driver_list);
1980 drv = matroxfb_driver_l(drv->node.next)) { 1986 drv = matroxfb_driver_l(drv->node.next)) {
@@ -1994,7 +2000,7 @@ static void matroxfb_register_device(struct matrox_fb_info* minfo) {
1994static void matroxfb_unregister_device(struct matrox_fb_info* minfo) { 2000static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
1995 int i; 2001 int i;
1996 2002
1997 list_del(&ACCESS_FBINFO(next_fb)); 2003 list_del(&minfo->next_fb);
1998 for (i = 0; i < minfo->drivers_count; i++) { 2004 for (i = 0; i < minfo->drivers_count; i++) {
1999 struct matroxfb_driver* drv = minfo->drivers[i]; 2005 struct matroxfb_driver* drv = minfo->drivers[i];
2000 2006
@@ -2010,9 +2016,6 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
2010 struct matrox_fb_info* minfo; 2016 struct matrox_fb_info* minfo;
2011 int err; 2017 int err;
2012 u_int32_t cmd; 2018 u_int32_t cmd;
2013#ifndef CONFIG_FB_MATROX_MULTIHEAD
2014 static int registered = 0;
2015#endif
2016 DBG(__func__) 2019 DBG(__func__)
2017 2020
2018 svid = pdev->subsystem_vendor; 2021 svid = pdev->subsystem_vendor;
@@ -2036,67 +2039,57 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
2036 return -1; 2039 return -1;
2037 } 2040 }
2038 2041
2039#ifdef CONFIG_FB_MATROX_MULTIHEAD
2040 minfo = kmalloc(sizeof(*minfo), GFP_KERNEL); 2042 minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
2041 if (!minfo) 2043 if (!minfo)
2042 return -1; 2044 return -1;
2043#else 2045 memset(minfo, 0, sizeof(*minfo));
2044 if (registered) /* singlehead driver... */
2045 return -1;
2046 minfo = &matroxfb_global_mxinfo;
2047#endif
2048 memset(MINFO, 0, sizeof(*MINFO));
2049 2046
2050 ACCESS_FBINFO(pcidev) = pdev; 2047 minfo->pcidev = pdev;
2051 ACCESS_FBINFO(dead) = 0; 2048 minfo->dead = 0;
2052 ACCESS_FBINFO(usecount) = 0; 2049 minfo->usecount = 0;
2053 ACCESS_FBINFO(userusecount) = 0; 2050 minfo->userusecount = 0;
2054 2051
2055 pci_set_drvdata(pdev, MINFO); 2052 pci_set_drvdata(pdev, minfo);
2056 /* DEVFLAGS */ 2053 /* DEVFLAGS */
2057 ACCESS_FBINFO(devflags.memtype) = memtype; 2054 minfo->devflags.memtype = memtype;
2058 if (memtype != -1) 2055 if (memtype != -1)
2059 noinit = 0; 2056 noinit = 0;
2060 if (cmd & PCI_COMMAND_MEMORY) { 2057 if (cmd & PCI_COMMAND_MEMORY) {
2061 ACCESS_FBINFO(devflags.novga) = novga; 2058 minfo->devflags.novga = novga;
2062 ACCESS_FBINFO(devflags.nobios) = nobios; 2059 minfo->devflags.nobios = nobios;
2063 ACCESS_FBINFO(devflags.noinit) = noinit; 2060 minfo->devflags.noinit = noinit;
2064 /* subsequent heads always needs initialization and must not enable BIOS */ 2061 /* subsequent heads always needs initialization and must not enable BIOS */
2065 novga = 1; 2062 novga = 1;
2066 nobios = 1; 2063 nobios = 1;
2067 noinit = 0; 2064 noinit = 0;
2068 } else { 2065 } else {
2069 ACCESS_FBINFO(devflags.novga) = 1; 2066 minfo->devflags.novga = 1;
2070 ACCESS_FBINFO(devflags.nobios) = 1; 2067 minfo->devflags.nobios = 1;
2071 ACCESS_FBINFO(devflags.noinit) = 0; 2068 minfo->devflags.noinit = 0;
2072 } 2069 }
2073 2070
2074 ACCESS_FBINFO(devflags.nopciretry) = no_pci_retry; 2071 minfo->devflags.nopciretry = no_pci_retry;
2075 ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24; 2072 minfo->devflags.mga_24bpp_fix = inv24;
2076 ACCESS_FBINFO(devflags.precise_width) = option_precise_width; 2073 minfo->devflags.precise_width = option_precise_width;
2077 ACCESS_FBINFO(devflags.sgram) = sgram; 2074 minfo->devflags.sgram = sgram;
2078 ACCESS_FBINFO(capable.cross4MB) = cross4MB; 2075 minfo->capable.cross4MB = cross4MB;
2079 2076
2080 spin_lock_init(&ACCESS_FBINFO(lock.DAC)); 2077 spin_lock_init(&minfo->lock.DAC);
2081 spin_lock_init(&ACCESS_FBINFO(lock.accel)); 2078 spin_lock_init(&minfo->lock.accel);
2082 init_rwsem(&ACCESS_FBINFO(crtc2.lock)); 2079 init_rwsem(&minfo->crtc2.lock);
2083 init_rwsem(&ACCESS_FBINFO(altout.lock)); 2080 init_rwsem(&minfo->altout.lock);
2084 ACCESS_FBINFO(irq_flags) = 0; 2081 mutex_init(&minfo->fbcon.mm_lock);
2085 init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); 2082 minfo->irq_flags = 0;
2086 init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); 2083 init_waitqueue_head(&minfo->crtc1.vsync.wait);
2087 ACCESS_FBINFO(crtc1.panpos) = -1; 2084 init_waitqueue_head(&minfo->crtc2.vsync.wait);
2088 2085 minfo->crtc1.panpos = -1;
2089 err = initMatrox2(PMINFO b); 2086
2087 err = initMatrox2(minfo, b);
2090 if (!err) { 2088 if (!err) {
2091#ifndef CONFIG_FB_MATROX_MULTIHEAD 2089 matroxfb_register_device(minfo);
2092 registered = 1;
2093#endif
2094 matroxfb_register_device(MINFO);
2095 return 0; 2090 return 0;
2096 } 2091 }
2097#ifdef CONFIG_FB_MATROX_MULTIHEAD
2098 kfree(minfo); 2092 kfree(minfo);
2099#endif
2100 return -1; 2093 return -1;
2101} 2094}
2102 2095
@@ -2104,7 +2097,7 @@ static void pci_remove_matrox(struct pci_dev* pdev) {
2104 struct matrox_fb_info* minfo; 2097 struct matrox_fb_info* minfo;
2105 2098
2106 minfo = pci_get_drvdata(pdev); 2099 minfo = pci_get_drvdata(pdev);
2107 matroxfb_remove(PMINFO 1); 2100 matroxfb_remove(minfo, 1);
2108} 2101}
2109 2102
2110static struct pci_device_id matroxfb_devices[] = { 2103static struct pci_device_id matroxfb_devices[] = {
@@ -2508,13 +2501,8 @@ module_param(inv24, int, 0);
2508MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)"); 2501MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
2509module_param(inverse, int, 0); 2502module_param(inverse, int, 0);
2510MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)"); 2503MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
2511#ifdef CONFIG_FB_MATROX_MULTIHEAD
2512module_param(dev, int, 0); 2504module_param(dev, int, 0);
2513MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)"); 2505MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
2514#else
2515module_param(dev, int, 0);
2516MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)");
2517#endif
2518module_param(vesa, int, 0); 2506module_param(vesa, int, 0);
2519MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)"); 2507MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
2520module_param(xres, int, 0); 2508module_param(xres, int, 0);
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 95883236c0cd..f3a4e15672d9 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -54,9 +54,6 @@
54#include "../macmodes.h" 54#include "../macmodes.h"
55#endif 55#endif
56 56
57/* always compile support for 32MB... It cost almost nothing */
58#define CONFIG_FB_MATROX_32MB
59
60#ifdef MATROXFB_DEBUG 57#ifdef MATROXFB_DEBUG
61 58
62#define DEBUG 59#define DEBUG
@@ -464,9 +461,7 @@ struct matrox_fb_info {
464 int nopciretry; 461 int nopciretry;
465 int noinit; 462 int noinit;
466 int sgram; 463 int sgram;
467#ifdef CONFIG_FB_MATROX_32MB
468 int support32MB; 464 int support32MB;
469#endif
470 465
471 int accelerator; 466 int accelerator;
472 int text_type_aux; 467 int text_type_aux;
@@ -524,47 +519,11 @@ struct matrox_fb_info {
524 519
525#define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon) 520#define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
526 521
527#ifdef CONFIG_FB_MATROX_MULTIHEAD
528#define ACCESS_FBINFO2(info, x) (info->x)
529#define ACCESS_FBINFO(x) ACCESS_FBINFO2(minfo,x)
530
531#define MINFO minfo
532
533#define WPMINFO2 struct matrox_fb_info* minfo
534#define WPMINFO WPMINFO2 ,
535#define CPMINFO2 const struct matrox_fb_info* minfo
536#define CPMINFO CPMINFO2 ,
537#define PMINFO2 minfo
538#define PMINFO PMINFO2 ,
539
540#define MINFO_FROM(x) struct matrox_fb_info* minfo = x
541#else
542
543extern struct matrox_fb_info matroxfb_global_mxinfo;
544
545#define ACCESS_FBINFO(x) (matroxfb_global_mxinfo.x)
546#define ACCESS_FBINFO2(info, x) (matroxfb_global_mxinfo.x)
547
548#define MINFO (&matroxfb_global_mxinfo)
549
550#define WPMINFO2 void
551#define WPMINFO
552#define CPMINFO2 void
553#define CPMINFO
554#define PMINFO2
555#define PMINFO
556
557#define MINFO_FROM(x)
558
559#endif
560
561#define MINFO_FROM_INFO(x) MINFO_FROM(info2minfo(x))
562
563struct matrox_switch { 522struct matrox_switch {
564 int (*preinit)(WPMINFO2); 523 int (*preinit)(struct matrox_fb_info *minfo);
565 void (*reset)(WPMINFO2); 524 void (*reset)(struct matrox_fb_info *minfo);
566 int (*init)(WPMINFO struct my_timming*); 525 int (*init)(struct matrox_fb_info *minfo, struct my_timming*);
567 void (*restore)(WPMINFO2); 526 void (*restore)(struct matrox_fb_info *minfo);
568}; 527};
569 528
570struct matroxfb_driver { 529struct matroxfb_driver {
@@ -727,11 +686,11 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
727#endif 686#endif
728#endif 687#endif
729 688
730#define mga_inb(addr) mga_readb(ACCESS_FBINFO(mmio.vbase), (addr)) 689#define mga_inb(addr) mga_readb(minfo->mmio.vbase, (addr))
731#define mga_inl(addr) mga_readl(ACCESS_FBINFO(mmio.vbase), (addr)) 690#define mga_inl(addr) mga_readl(minfo->mmio.vbase, (addr))
732#define mga_outb(addr,val) mga_writeb(ACCESS_FBINFO(mmio.vbase), (addr), (val)) 691#define mga_outb(addr,val) mga_writeb(minfo->mmio.vbase, (addr), (val))
733#define mga_outw(addr,val) mga_writew(ACCESS_FBINFO(mmio.vbase), (addr), (val)) 692#define mga_outw(addr,val) mga_writew(minfo->mmio.vbase, (addr), (val))
734#define mga_outl(addr,val) mga_writel(ACCESS_FBINFO(mmio.vbase), (addr), (val)) 693#define mga_outl(addr,val) mga_writel(minfo->mmio.vbase, (addr), (val))
735#define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1)) 694#define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1))
736#define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port)) 695#define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port))
737 696
@@ -750,19 +709,20 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
750#define isMilleniumII(x) (0) 709#define isMilleniumII(x) (0)
751#endif 710#endif
752 711
753#define matroxfb_DAC_lock() spin_lock(&ACCESS_FBINFO(lock.DAC)) 712#define matroxfb_DAC_lock() spin_lock(&minfo->lock.DAC)
754#define matroxfb_DAC_unlock() spin_unlock(&ACCESS_FBINFO(lock.DAC)) 713#define matroxfb_DAC_unlock() spin_unlock(&minfo->lock.DAC)
755#define matroxfb_DAC_lock_irqsave(flags) spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC),flags) 714#define matroxfb_DAC_lock_irqsave(flags) spin_lock_irqsave(&minfo->lock.DAC, flags)
756#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC),flags) 715#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&minfo->lock.DAC, flags)
757extern void matroxfb_DAC_out(CPMINFO int reg, int val); 716extern void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg,
758extern int matroxfb_DAC_in(CPMINFO int reg); 717 int val);
718extern int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg);
759extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt); 719extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
760extern int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc); 720extern int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc);
761extern int matroxfb_enable_irq(WPMINFO int reenable); 721extern int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable);
762 722
763#ifdef MATROXFB_USE_SPINLOCKS 723#ifdef MATROXFB_USE_SPINLOCKS
764#define CRITBEGIN spin_lock_irqsave(&ACCESS_FBINFO(lock.accel), critflags); 724#define CRITBEGIN spin_lock_irqsave(&minfo->lock.accel, critflags);
765#define CRITEND spin_unlock_irqrestore(&ACCESS_FBINFO(lock.accel), critflags); 725#define CRITEND spin_unlock_irqrestore(&minfo->lock.accel, critflags);
766#define CRITFLAGS unsigned long critflags; 726#define CRITFLAGS unsigned long critflags;
767#else 727#else
768#define CRITBEGIN 728#define CRITBEGIN
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 7ac4c5f6145d..78414baa5a54 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -65,7 +65,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
65 unsigned int pos) { 65 unsigned int pos) {
66 u_int32_t tmp; 66 u_int32_t tmp;
67 u_int32_t datactl; 67 u_int32_t datactl;
68 MINFO_FROM(m2info->primary_dev); 68 struct matrox_fb_info *minfo = m2info->primary_dev;
69 69
70 switch (mode) { 70 switch (mode) {
71 case 15: 71 case 15:
@@ -81,11 +81,11 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
81 } 81 }
82 tmp |= 0x00000001; /* enable CRTC2 */ 82 tmp |= 0x00000001; /* enable CRTC2 */
83 datactl = 0; 83 datactl = 0;
84 if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { 84 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
85 if (ACCESS_FBINFO(devflags.g450dac)) { 85 if (minfo->devflags.g450dac) {
86 tmp |= 0x00000006; /* source from secondary pixel PLL */ 86 tmp |= 0x00000006; /* source from secondary pixel PLL */
87 /* no vidrst when in monitor mode */ 87 /* no vidrst when in monitor mode */
88 if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { 88 if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
89 tmp |= 0xC0001000; /* Enable H/V vidrst */ 89 tmp |= 0xC0001000; /* Enable H/V vidrst */
90 } 90 }
91 } else { 91 } else {
@@ -93,11 +93,11 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
93 tmp |= 0xC0000000; /* enable vvidrst & hvidrst */ 93 tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
94 /* MGA TVO is our clock source */ 94 /* MGA TVO is our clock source */
95 } 95 }
96 } else if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) { 96 } else if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
97 tmp |= 0x00000004; /* source from pixclock */ 97 tmp |= 0x00000004; /* source from pixclock */
98 /* PIXPLL is our clock source */ 98 /* PIXPLL is our clock source */
99 } 99 }
100 if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) { 100 if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
101 tmp |= 0x00100000; /* connect CRTC2 to DAC */ 101 tmp |= 0x00100000; /* connect CRTC2 to DAC */
102 } 102 }
103 if (mt->interlaced) { 103 if (mt->interlaced) {
@@ -146,7 +146,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
146 } 146 }
147 } 147 }
148 mga_outl(0x3C10, tmp); 148 mga_outl(0x3C10, tmp);
149 ACCESS_FBINFO(hw).crtc2.ctl = tmp; 149 minfo->hw.crtc2.ctl = tmp;
150 150
151 tmp = mt->VDisplay << 16; /* line compare */ 151 tmp = mt->VDisplay << 16; /* line compare */
152 if (mt->sync & FB_SYNC_HOR_HIGH_ACT) 152 if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -157,10 +157,10 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
157} 157}
158 158
159static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) { 159static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
160 MINFO_FROM(m2info->primary_dev); 160 struct matrox_fb_info *minfo = m2info->primary_dev;
161 161
162 mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */ 162 mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */
163 ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004; 163 minfo->hw.crtc2.ctl = 0x00000004;
164} 164}
165 165
166static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, 166static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
@@ -168,7 +168,7 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
168 unsigned int pos; 168 unsigned int pos;
169 unsigned int linelen; 169 unsigned int linelen;
170 unsigned int pixelsize; 170 unsigned int pixelsize;
171 MINFO_FROM(m2info->primary_dev); 171 struct matrox_fb_info *minfo = m2info->primary_dev;
172 172
173 m2info->fbcon.var.xoffset = var->xoffset; 173 m2info->fbcon.var.xoffset = var->xoffset;
174 m2info->fbcon.var.yoffset = var->yoffset; 174 m2info->fbcon.var.yoffset = var->yoffset;
@@ -260,15 +260,15 @@ static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,
260 260
261static int matroxfb_dh_open(struct fb_info* info, int user) { 261static int matroxfb_dh_open(struct fb_info* info, int user) {
262#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) 262#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
263 MINFO_FROM(m2info->primary_dev); 263 struct matrox_fb_info *minfo = m2info->primary_dev;
264 264
265 if (MINFO) { 265 if (minfo) {
266 int err; 266 int err;
267 267
268 if (ACCESS_FBINFO(dead)) { 268 if (minfo->dead) {
269 return -ENXIO; 269 return -ENXIO;
270 } 270 }
271 err = ACCESS_FBINFO(fbops).fb_open(&ACCESS_FBINFO(fbcon), user); 271 err = minfo->fbops.fb_open(&minfo->fbcon, user);
272 if (err) { 272 if (err) {
273 return err; 273 return err;
274 } 274 }
@@ -280,16 +280,21 @@ static int matroxfb_dh_open(struct fb_info* info, int user) {
280static int matroxfb_dh_release(struct fb_info* info, int user) { 280static int matroxfb_dh_release(struct fb_info* info, int user) {
281#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) 281#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
282 int err = 0; 282 int err = 0;
283 MINFO_FROM(m2info->primary_dev); 283 struct matrox_fb_info *minfo = m2info->primary_dev;
284 284
285 if (MINFO) { 285 if (minfo) {
286 err = ACCESS_FBINFO(fbops).fb_release(&ACCESS_FBINFO(fbcon), user); 286 err = minfo->fbops.fb_release(&minfo->fbcon, user);
287 } 287 }
288 return err; 288 return err;
289#undef m2info 289#undef m2info
290} 290}
291 291
292static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { 292/*
293 * This function is called before the register_framebuffer so
294 * no locking is needed.
295 */
296static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info)
297{
293 struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; 298 struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
294 299
295 strcpy(fix->id, "MATROX DH"); 300 strcpy(fix->id, "MATROX DH");
@@ -321,7 +326,7 @@ static int matroxfb_dh_set_par(struct fb_info* info) {
321 int mode; 326 int mode;
322 int err; 327 int err;
323 struct fb_var_screeninfo* var = &info->var; 328 struct fb_var_screeninfo* var = &info->var;
324 MINFO_FROM(m2info->primary_dev); 329 struct matrox_fb_info *minfo = m2info->primary_dev;
325 330
326 if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0) 331 if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0)
327 return err; 332 return err;
@@ -347,39 +352,39 @@ static int matroxfb_dh_set_par(struct fb_info* info) {
347 pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3; 352 pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3;
348 pos += m2info->video.offbase; 353 pos += m2info->video.offbase;
349 cnt = 0; 354 cnt = 0;
350 down_read(&ACCESS_FBINFO(altout).lock); 355 down_read(&minfo->altout.lock);
351 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 356 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
352 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) { 357 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
353 cnt++; 358 cnt++;
354 if (ACCESS_FBINFO(outputs[out]).output->compute) { 359 if (minfo->outputs[out].output->compute) {
355 ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt); 360 minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
356 } 361 }
357 } 362 }
358 } 363 }
359 ACCESS_FBINFO(crtc2).pixclock = mt.pixclock; 364 minfo->crtc2.pixclock = mt.pixclock;
360 ACCESS_FBINFO(crtc2).mnp = mt.mnp; 365 minfo->crtc2.mnp = mt.mnp;
361 up_read(&ACCESS_FBINFO(altout).lock); 366 up_read(&minfo->altout.lock);
362 if (cnt) { 367 if (cnt) {
363 matroxfb_dh_restore(m2info, &mt, mode, pos); 368 matroxfb_dh_restore(m2info, &mt, mode, pos);
364 } else { 369 } else {
365 matroxfb_dh_disable(m2info); 370 matroxfb_dh_disable(m2info);
366 } 371 }
367 DAC1064_global_init(PMINFO2); 372 DAC1064_global_init(minfo);
368 DAC1064_global_restore(PMINFO2); 373 DAC1064_global_restore(minfo);
369 down_read(&ACCESS_FBINFO(altout).lock); 374 down_read(&minfo->altout.lock);
370 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 375 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
371 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 && 376 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
372 ACCESS_FBINFO(outputs[out]).output->program) { 377 minfo->outputs[out].output->program) {
373 ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data); 378 minfo->outputs[out].output->program(minfo->outputs[out].data);
374 } 379 }
375 } 380 }
376 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 381 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
377 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 && 382 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
378 ACCESS_FBINFO(outputs[out]).output->start) { 383 minfo->outputs[out].output->start) {
379 ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data); 384 minfo->outputs[out].output->start(minfo->outputs[out].data);
380 } 385 }
381 } 386 }
382 up_read(&ACCESS_FBINFO(altout).lock); 387 up_read(&minfo->altout.lock);
383 } 388 }
384 m2info->initialized = 1; 389 m2info->initialized = 1;
385 return 0; 390 return 0;
@@ -394,9 +399,9 @@ static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, struct fb_info
394} 399}
395 400
396static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) { 401static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
397 MINFO_FROM(m2info->primary_dev); 402 struct matrox_fb_info *minfo = m2info->primary_dev;
398 403
399 matroxfb_enable_irq(PMINFO 0); 404 matroxfb_enable_irq(minfo, 0);
400 memset(vblank, 0, sizeof(*vblank)); 405 memset(vblank, 0, sizeof(*vblank));
401 vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK; 406 vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
402 /* mask out reserved bits + field number (odd/even) */ 407 /* mask out reserved bits + field number (odd/even) */
@@ -404,11 +409,11 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru
404 /* compatibility stuff */ 409 /* compatibility stuff */
405 if (vblank->vcount >= m2info->fbcon.var.yres) 410 if (vblank->vcount >= m2info->fbcon.var.yres)
406 vblank->flags |= FB_VBLANK_VBLANKING; 411 vblank->flags |= FB_VBLANK_VBLANKING;
407 if (test_bit(0, &ACCESS_FBINFO(irq_flags))) { 412 if (test_bit(0, &minfo->irq_flags)) {
408 vblank->flags |= FB_VBLANK_HAVE_COUNT; 413 vblank->flags |= FB_VBLANK_HAVE_COUNT;
409 /* Only one writer, aligned int value... 414 /* Only one writer, aligned int value...
410 it should work without lock and without atomic_t */ 415 it should work without lock and without atomic_t */
411 vblank->count = ACCESS_FBINFO(crtc2).vsync.cnt; 416 vblank->count = minfo->crtc2.vsync.cnt;
412 } 417 }
413 return 0; 418 return 0;
414} 419}
@@ -418,7 +423,7 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
418 unsigned long arg) 423 unsigned long arg)
419{ 424{
420#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) 425#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
421 MINFO_FROM(m2info->primary_dev); 426 struct matrox_fb_info *minfo = m2info->primary_dev;
422 427
423 DBG(__func__) 428 DBG(__func__)
424 429
@@ -444,13 +449,13 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
444 449
445 if (crt != 0) 450 if (crt != 0)
446 return -ENODEV; 451 return -ENODEV;
447 return matroxfb_wait_for_sync(PMINFO 1); 452 return matroxfb_wait_for_sync(minfo, 1);
448 } 453 }
449 case MATROXFB_SET_OUTPUT_MODE: 454 case MATROXFB_SET_OUTPUT_MODE:
450 case MATROXFB_GET_OUTPUT_MODE: 455 case MATROXFB_GET_OUTPUT_MODE:
451 case MATROXFB_GET_ALL_OUTPUTS: 456 case MATROXFB_GET_ALL_OUTPUTS:
452 { 457 {
453 return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg); 458 return minfo->fbcon.fbops->fb_ioctl(&minfo->fbcon, cmd, arg);
454 } 459 }
455 case MATROXFB_SET_OUTPUT_CONNECTION: 460 case MATROXFB_SET_OUTPUT_CONNECTION:
456 { 461 {
@@ -464,9 +469,9 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
464 if (tmp & (1 << out)) { 469 if (tmp & (1 << out)) {
465 if (out >= MATROXFB_MAX_OUTPUTS) 470 if (out >= MATROXFB_MAX_OUTPUTS)
466 return -ENXIO; 471 return -ENXIO;
467 if (!ACCESS_FBINFO(outputs[out]).output) 472 if (!minfo->outputs[out].output)
468 return -ENXIO; 473 return -ENXIO;
469 switch (ACCESS_FBINFO(outputs[out]).src) { 474 switch (minfo->outputs[out].src) {
470 case MATROXFB_SRC_NONE: 475 case MATROXFB_SRC_NONE:
471 case MATROXFB_SRC_CRTC2: 476 case MATROXFB_SRC_CRTC2:
472 break; 477 break;
@@ -475,22 +480,22 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
475 } 480 }
476 } 481 }
477 } 482 }
478 if (ACCESS_FBINFO(devflags.panellink)) { 483 if (minfo->devflags.panellink) {
479 if (tmp & MATROXFB_OUTPUT_CONN_DFP) 484 if (tmp & MATROXFB_OUTPUT_CONN_DFP)
480 return -EINVAL; 485 return -EINVAL;
481 if ((ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) && tmp) 486 if ((minfo->outputs[2].src == MATROXFB_SRC_CRTC1) && tmp)
482 return -EBUSY; 487 return -EBUSY;
483 } 488 }
484 changes = 0; 489 changes = 0;
485 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 490 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
486 if (tmp & (1 << out)) { 491 if (tmp & (1 << out)) {
487 if (ACCESS_FBINFO(outputs[out]).src != MATROXFB_SRC_CRTC2) { 492 if (minfo->outputs[out].src != MATROXFB_SRC_CRTC2) {
488 changes = 1; 493 changes = 1;
489 ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_CRTC2; 494 minfo->outputs[out].src = MATROXFB_SRC_CRTC2;
490 } 495 }
491 } else if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) { 496 } else if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
492 changes = 1; 497 changes = 1;
493 ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_NONE; 498 minfo->outputs[out].src = MATROXFB_SRC_NONE;
494 } 499 }
495 } 500 }
496 if (!changes) 501 if (!changes)
@@ -504,7 +509,7 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
504 int out; 509 int out;
505 510
506 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 511 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
507 if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) { 512 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
508 conn |= 1 << out; 513 conn |= 1 << out;
509 } 514 }
510 } 515 }
@@ -518,8 +523,8 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
518 int out; 523 int out;
519 524
520 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { 525 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
521 if (ACCESS_FBINFO(outputs[out]).output) { 526 if (minfo->outputs[out].output) {
522 switch (ACCESS_FBINFO(outputs[out]).src) { 527 switch (minfo->outputs[out].src) {
523 case MATROXFB_SRC_NONE: 528 case MATROXFB_SRC_NONE:
524 case MATROXFB_SRC_CRTC2: 529 case MATROXFB_SRC_CRTC2:
525 tmp |= 1 << out; 530 tmp |= 1 << out;
@@ -527,9 +532,9 @@ static int matroxfb_dh_ioctl(struct fb_info *info,
527 } 532 }
528 } 533 }
529 } 534 }
530 if (ACCESS_FBINFO(devflags.panellink)) { 535 if (minfo->devflags.panellink) {
531 tmp &= ~MATROXFB_OUTPUT_CONN_DFP; 536 tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
532 if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) { 537 if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) {
533 tmp = 0; 538 tmp = 0;
534 } 539 }
535 } 540 }
@@ -590,7 +595,9 @@ static struct fb_var_screeninfo matroxfb_dh_defined = {
590 0, {0,0,0,0,0} 595 0, {0,0,0,0,0}
591}; 596};
592 597
593static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { 598static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
599 struct matroxfb_dh_fb_info *m2info)
600{
594#define minfo (m2info->primary_dev) 601#define minfo (m2info->primary_dev)
595 void* oldcrtc2; 602 void* oldcrtc2;
596 603
@@ -606,21 +613,21 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
606 if (mem < 64*1024) 613 if (mem < 64*1024)
607 mem *= 1024; 614 mem *= 1024;
608 mem &= ~0x00000FFF; /* PAGE_MASK? */ 615 mem &= ~0x00000FFF; /* PAGE_MASK? */
609 if (ACCESS_FBINFO(video.len_usable) + mem <= ACCESS_FBINFO(video.len)) 616 if (minfo->video.len_usable + mem <= minfo->video.len)
610 m2info->video.offbase = ACCESS_FBINFO(video.len) - mem; 617 m2info->video.offbase = minfo->video.len - mem;
611 else if (ACCESS_FBINFO(video.len) < mem) { 618 else if (minfo->video.len < mem) {
612 return -ENOMEM; 619 return -ENOMEM;
613 } else { /* check yres on first head... */ 620 } else { /* check yres on first head... */
614 m2info->video.borrowed = mem; 621 m2info->video.borrowed = mem;
615 ACCESS_FBINFO(video.len_usable) -= mem; 622 minfo->video.len_usable -= mem;
616 m2info->video.offbase = ACCESS_FBINFO(video.len_usable); 623 m2info->video.offbase = minfo->video.len_usable;
617 } 624 }
618 m2info->video.base = ACCESS_FBINFO(video.base) + m2info->video.offbase; 625 m2info->video.base = minfo->video.base + m2info->video.offbase;
619 m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem; 626 m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
620 m2info->video.vbase.vaddr = vaddr_va(ACCESS_FBINFO(video.vbase)) + m2info->video.offbase; 627 m2info->video.vbase.vaddr = vaddr_va(minfo->video.vbase) + m2info->video.offbase;
621 m2info->mmio.base = ACCESS_FBINFO(mmio.base); 628 m2info->mmio.base = minfo->mmio.base;
622 m2info->mmio.vbase = ACCESS_FBINFO(mmio.vbase); 629 m2info->mmio.vbase = minfo->mmio.vbase;
623 m2info->mmio.len = ACCESS_FBINFO(mmio.len); 630 m2info->mmio.len = minfo->mmio.len;
624 631
625 matroxfb_dh_init_fix(m2info); 632 matroxfb_dh_init_fix(m2info);
626 if (register_framebuffer(&m2info->fbcon)) { 633 if (register_framebuffer(&m2info->fbcon)) {
@@ -628,10 +635,10 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
628 } 635 }
629 if (!m2info->initialized) 636 if (!m2info->initialized)
630 fb_set_var(&m2info->fbcon, &matroxfb_dh_defined); 637 fb_set_var(&m2info->fbcon, &matroxfb_dh_defined);
631 down_write(&ACCESS_FBINFO(crtc2.lock)); 638 down_write(&minfo->crtc2.lock);
632 oldcrtc2 = ACCESS_FBINFO(crtc2.info); 639 oldcrtc2 = minfo->crtc2.info;
633 ACCESS_FBINFO(crtc2.info) = m2info; 640 minfo->crtc2.info = m2info;
634 up_write(&ACCESS_FBINFO(crtc2.lock)); 641 up_write(&minfo->crtc2.lock);
635 if (oldcrtc2) { 642 if (oldcrtc2) {
636 printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n", 643 printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
637 oldcrtc2); 644 oldcrtc2);
@@ -644,12 +651,12 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
644 651
645static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) { 652static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) {
646#define minfo (m2info->primary_dev) 653#define minfo (m2info->primary_dev)
647 if (matroxfb_dh_regit(PMINFO m2info)) { 654 if (matroxfb_dh_regit(minfo, m2info)) {
648 printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n"); 655 printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n");
649 return -1; 656 return -1;
650 } 657 }
651 printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n", 658 printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n",
652 ACCESS_FBINFO(fbcon.node), m2info->fbcon.node); 659 minfo->fbcon.node, m2info->fbcon.node);
653 m2info->fbcon_registered = 1; 660 m2info->fbcon_registered = 1;
654 return 0; 661 return 0;
655#undef minfo 662#undef minfo
@@ -661,11 +668,11 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
661 int id; 668 int id;
662 struct matroxfb_dh_fb_info* crtc2; 669 struct matroxfb_dh_fb_info* crtc2;
663 670
664 down_write(&ACCESS_FBINFO(crtc2.lock)); 671 down_write(&minfo->crtc2.lock);
665 crtc2 = ACCESS_FBINFO(crtc2.info); 672 crtc2 = minfo->crtc2.info;
666 if (crtc2 == m2info) 673 if (crtc2 == m2info)
667 ACCESS_FBINFO(crtc2.info) = NULL; 674 minfo->crtc2.info = NULL;
668 up_write(&ACCESS_FBINFO(crtc2.lock)); 675 up_write(&minfo->crtc2.lock);
669 if (crtc2 != m2info) { 676 if (crtc2 != m2info) {
670 printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n", 677 printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
671 crtc2, m2info); 678 crtc2, m2info);
@@ -675,7 +682,7 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
675 id = m2info->fbcon.node; 682 id = m2info->fbcon.node;
676 unregister_framebuffer(&m2info->fbcon); 683 unregister_framebuffer(&m2info->fbcon);
677 /* return memory back to primary head */ 684 /* return memory back to primary head */
678 ACCESS_FBINFO(video.len_usable) += m2info->video.borrowed; 685 minfo->video.len_usable += m2info->video.borrowed;
679 printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id); 686 printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id);
680 m2info->fbcon_registered = 0; 687 m2info->fbcon_registered = 0;
681 } 688 }
@@ -686,14 +693,14 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
686 struct matroxfb_dh_fb_info* m2info; 693 struct matroxfb_dh_fb_info* m2info;
687 694
688 /* hardware is CRTC2 incapable... */ 695 /* hardware is CRTC2 incapable... */
689 if (!ACCESS_FBINFO(devflags.crtc2)) 696 if (!minfo->devflags.crtc2)
690 return NULL; 697 return NULL;
691 m2info = kzalloc(sizeof(*m2info), GFP_KERNEL); 698 m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
692 if (!m2info) { 699 if (!m2info) {
693 printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n"); 700 printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
694 return NULL; 701 return NULL;
695 } 702 }
696 m2info->primary_dev = MINFO; 703 m2info->primary_dev = minfo;
697 if (matroxfb_dh_registerfb(m2info)) { 704 if (matroxfb_dh_registerfb(m2info)) {
698 kfree(m2info); 705 kfree(m2info);
699 printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n"); 706 printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index 6209a761f674..cff0546ea6fd 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -80,52 +80,59 @@ static int get_ctrl_id(__u32 v4l2_id) {
80 return -EINVAL; 80 return -EINVAL;
81} 81}
82 82
83static inline int* get_ctrl_ptr(WPMINFO unsigned int idx) { 83static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx)
84 return (int*)((char*)MINFO + g450_controls[idx].control); 84{
85 return (int*)((char*)minfo + g450_controls[idx].control);
85} 86}
86 87
87static void tvo_fill_defaults(WPMINFO2) { 88static void tvo_fill_defaults(struct matrox_fb_info *minfo)
89{
88 unsigned int i; 90 unsigned int i;
89 91
90 for (i = 0; i < G450CTRLS; i++) { 92 for (i = 0; i < G450CTRLS; i++) {
91 *get_ctrl_ptr(PMINFO i) = g450_controls[i].desc.default_value; 93 *get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value;
92 } 94 }
93} 95}
94 96
95static int cve2_get_reg(WPMINFO int reg) { 97static int cve2_get_reg(struct matrox_fb_info *minfo, int reg)
98{
96 unsigned long flags; 99 unsigned long flags;
97 int val; 100 int val;
98 101
99 matroxfb_DAC_lock_irqsave(flags); 102 matroxfb_DAC_lock_irqsave(flags);
100 matroxfb_DAC_out(PMINFO 0x87, reg); 103 matroxfb_DAC_out(minfo, 0x87, reg);
101 val = matroxfb_DAC_in(PMINFO 0x88); 104 val = matroxfb_DAC_in(minfo, 0x88);
102 matroxfb_DAC_unlock_irqrestore(flags); 105 matroxfb_DAC_unlock_irqrestore(flags);
103 return val; 106 return val;
104} 107}
105 108
106static void cve2_set_reg(WPMINFO int reg, int val) { 109static void cve2_set_reg(struct matrox_fb_info *minfo, int reg, int val)
110{
107 unsigned long flags; 111 unsigned long flags;
108 112
109 matroxfb_DAC_lock_irqsave(flags); 113 matroxfb_DAC_lock_irqsave(flags);
110 matroxfb_DAC_out(PMINFO 0x87, reg); 114 matroxfb_DAC_out(minfo, 0x87, reg);
111 matroxfb_DAC_out(PMINFO 0x88, val); 115 matroxfb_DAC_out(minfo, 0x88, val);
112 matroxfb_DAC_unlock_irqrestore(flags); 116 matroxfb_DAC_unlock_irqrestore(flags);
113} 117}
114 118
115static void cve2_set_reg10(WPMINFO int reg, int val) { 119static void cve2_set_reg10(struct matrox_fb_info *minfo, int reg, int val)
120{
116 unsigned long flags; 121 unsigned long flags;
117 122
118 matroxfb_DAC_lock_irqsave(flags); 123 matroxfb_DAC_lock_irqsave(flags);
119 matroxfb_DAC_out(PMINFO 0x87, reg); 124 matroxfb_DAC_out(minfo, 0x87, reg);
120 matroxfb_DAC_out(PMINFO 0x88, val >> 2); 125 matroxfb_DAC_out(minfo, 0x88, val >> 2);
121 matroxfb_DAC_out(PMINFO 0x87, reg + 1); 126 matroxfb_DAC_out(minfo, 0x87, reg + 1);
122 matroxfb_DAC_out(PMINFO 0x88, val & 3); 127 matroxfb_DAC_out(minfo, 0x88, val & 3);
123 matroxfb_DAC_unlock_irqrestore(flags); 128 matroxfb_DAC_unlock_irqrestore(flags);
124} 129}
125 130
126static void g450_compute_bwlevel(CPMINFO int *bl, int *wl) { 131static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl,
127 const int b = ACCESS_FBINFO(altout.tvo_params.brightness) + BLMIN; 132 int *wl)
128 const int c = ACCESS_FBINFO(altout.tvo_params.contrast); 133{
134 const int b = minfo->altout.tvo_params.brightness + BLMIN;
135 const int c = minfo->altout.tvo_params.contrast;
129 136
130 *bl = max(b - c, BLMIN); 137 *bl = max(b - c, BLMIN);
131 *wl = min(b + c, WLMAX); 138 *wl = min(b + c, WLMAX);
@@ -154,7 +161,7 @@ static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) {
154 161
155static int g450_set_ctrl(void* md, struct v4l2_control *p) { 162static int g450_set_ctrl(void* md, struct v4l2_control *p) {
156 int i; 163 int i;
157 MINFO_FROM(md); 164 struct matrox_fb_info *minfo = md;
158 165
159 i = get_ctrl_id(p->id); 166 i = get_ctrl_id(p->id);
160 if (i < 0) return -EINVAL; 167 if (i < 0) return -EINVAL;
@@ -162,7 +169,7 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) {
162 /* 169 /*
163 * Check if changed. 170 * Check if changed.
164 */ 171 */
165 if (p->value == *get_ctrl_ptr(PMINFO i)) return 0; 172 if (p->value == *get_ctrl_ptr(minfo, i)) return 0;
166 173
167 /* 174 /*
168 * Check limits. 175 * Check limits.
@@ -173,31 +180,31 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) {
173 /* 180 /*
174 * Store new value. 181 * Store new value.
175 */ 182 */
176 *get_ctrl_ptr(PMINFO i) = p->value; 183 *get_ctrl_ptr(minfo, i) = p->value;
177 184
178 switch (p->id) { 185 switch (p->id) {
179 case V4L2_CID_BRIGHTNESS: 186 case V4L2_CID_BRIGHTNESS:
180 case V4L2_CID_CONTRAST: 187 case V4L2_CID_CONTRAST:
181 { 188 {
182 int blacklevel, whitelevel; 189 int blacklevel, whitelevel;
183 g450_compute_bwlevel(PMINFO &blacklevel, &whitelevel); 190 g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
184 cve2_set_reg10(PMINFO 0x0e, blacklevel); 191 cve2_set_reg10(minfo, 0x0e, blacklevel);
185 cve2_set_reg10(PMINFO 0x1e, whitelevel); 192 cve2_set_reg10(minfo, 0x1e, whitelevel);
186 } 193 }
187 break; 194 break;
188 case V4L2_CID_SATURATION: 195 case V4L2_CID_SATURATION:
189 cve2_set_reg(PMINFO 0x20, p->value); 196 cve2_set_reg(minfo, 0x20, p->value);
190 cve2_set_reg(PMINFO 0x22, p->value); 197 cve2_set_reg(minfo, 0x22, p->value);
191 break; 198 break;
192 case V4L2_CID_HUE: 199 case V4L2_CID_HUE:
193 cve2_set_reg(PMINFO 0x25, p->value); 200 cve2_set_reg(minfo, 0x25, p->value);
194 break; 201 break;
195 case MATROXFB_CID_TESTOUT: 202 case MATROXFB_CID_TESTOUT:
196 { 203 {
197 unsigned char val = cve2_get_reg (PMINFO 0x05); 204 unsigned char val = cve2_get_reg(minfo, 0x05);
198 if (p->value) val |= 0x02; 205 if (p->value) val |= 0x02;
199 else val &= ~0x02; 206 else val &= ~0x02;
200 cve2_set_reg(PMINFO 0x05, val); 207 cve2_set_reg(minfo, 0x05, val);
201 } 208 }
202 break; 209 break;
203 } 210 }
@@ -208,11 +215,11 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) {
208 215
209static int g450_get_ctrl(void* md, struct v4l2_control *p) { 216static int g450_get_ctrl(void* md, struct v4l2_control *p) {
210 int i; 217 int i;
211 MINFO_FROM(md); 218 struct matrox_fb_info *minfo = md;
212 219
213 i = get_ctrl_id(p->id); 220 i = get_ctrl_id(p->id);
214 if (i < 0) return -EINVAL; 221 if (i < 0) return -EINVAL;
215 p->value = *get_ctrl_ptr(PMINFO i); 222 p->value = *get_ctrl_ptr(minfo, i);
216 return 0; 223 return 0;
217} 224}
218 225
@@ -226,7 +233,9 @@ struct output_desc {
226 unsigned int v_total; 233 unsigned int v_total;
227}; 234};
228 235
229static void computeRegs(WPMINFO struct mavenregs* r, struct my_timming* mt, const struct output_desc* outd) { 236static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r,
237 struct my_timming *mt, const struct output_desc *outd)
238{
230 u_int32_t chromasc; 239 u_int32_t chromasc;
231 u_int32_t hlen; 240 u_int32_t hlen;
232 u_int32_t hsl; 241 u_int32_t hsl;
@@ -251,10 +260,10 @@ static void computeRegs(WPMINFO struct mavenregs* r, struct my_timming* mt, cons
251 260
252 dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic); 261 dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic);
253 262
254 mnp = matroxfb_g450_setclk(PMINFO piic, M_VIDEO_PLL); 263 mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL);
255 264
256 mt->mnp = mnp; 265 mt->mnp = mnp;
257 mt->pixclock = g450_mnp2f(PMINFO mnp); 266 mt->pixclock = g450_mnp2f(minfo, mnp);
258 267
259 dprintk(KERN_DEBUG "MNP=%08X\n", mnp); 268 dprintk(KERN_DEBUG "MNP=%08X\n", mnp);
260 269
@@ -490,65 +499,67 @@ static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct outp
490 return; 499 return;
491} 500}
492 501
493#define LR(x) cve2_set_reg(PMINFO (x), m->regs[(x)]) 502#define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)])
494static void cve2_init_TV(WPMINFO const struct mavenregs* m) { 503static void cve2_init_TV(struct matrox_fb_info *minfo,
504 const struct mavenregs *m)
505{
495 int i; 506 int i;
496 507
497 LR(0x80); 508 LR(0x80);
498 LR(0x82); LR(0x83); 509 LR(0x82); LR(0x83);
499 LR(0x84); LR(0x85); 510 LR(0x84); LR(0x85);
500 511
501 cve2_set_reg(PMINFO 0x3E, 0x01); 512 cve2_set_reg(minfo, 0x3E, 0x01);
502 513
503 for (i = 0; i < 0x3E; i++) { 514 for (i = 0; i < 0x3E; i++) {
504 LR(i); 515 LR(i);
505 } 516 }
506 cve2_set_reg(PMINFO 0x3E, 0x00); 517 cve2_set_reg(minfo, 0x3E, 0x00);
507} 518}
508 519
509static int matroxfb_g450_compute(void* md, struct my_timming* mt) { 520static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
510 MINFO_FROM(md); 521 struct matrox_fb_info *minfo = md;
511 522
512 dprintk(KERN_DEBUG "Computing, mode=%u\n", ACCESS_FBINFO(outputs[1]).mode); 523 dprintk(KERN_DEBUG "Computing, mode=%u\n", minfo->outputs[1].mode);
513 524
514 if (mt->crtc == MATROXFB_SRC_CRTC2 && 525 if (mt->crtc == MATROXFB_SRC_CRTC2 &&
515 ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { 526 minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
516 const struct output_desc* outd; 527 const struct output_desc* outd;
517 528
518 cve2_init_TVdata(ACCESS_FBINFO(outputs[1]).mode, &ACCESS_FBINFO(hw).maven, &outd); 529 cve2_init_TVdata(minfo->outputs[1].mode, &minfo->hw.maven, &outd);
519 { 530 {
520 int blacklevel, whitelevel; 531 int blacklevel, whitelevel;
521 g450_compute_bwlevel(PMINFO &blacklevel, &whitelevel); 532 g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
522 ACCESS_FBINFO(hw).maven.regs[0x0E] = blacklevel >> 2; 533 minfo->hw.maven.regs[0x0E] = blacklevel >> 2;
523 ACCESS_FBINFO(hw).maven.regs[0x0F] = blacklevel & 3; 534 minfo->hw.maven.regs[0x0F] = blacklevel & 3;
524 ACCESS_FBINFO(hw).maven.regs[0x1E] = whitelevel >> 2; 535 minfo->hw.maven.regs[0x1E] = whitelevel >> 2;
525 ACCESS_FBINFO(hw).maven.regs[0x1F] = whitelevel & 3; 536 minfo->hw.maven.regs[0x1F] = whitelevel & 3;
526 537
527 ACCESS_FBINFO(hw).maven.regs[0x20] = 538 minfo->hw.maven.regs[0x20] =
528 ACCESS_FBINFO(hw).maven.regs[0x22] = ACCESS_FBINFO(altout.tvo_params.saturation); 539 minfo->hw.maven.regs[0x22] = minfo->altout.tvo_params.saturation;
529 540
530 ACCESS_FBINFO(hw).maven.regs[0x25] = ACCESS_FBINFO(altout.tvo_params.hue); 541 minfo->hw.maven.regs[0x25] = minfo->altout.tvo_params.hue;
531 542
532 if (ACCESS_FBINFO(altout.tvo_params.testout)) { 543 if (minfo->altout.tvo_params.testout) {
533 ACCESS_FBINFO(hw).maven.regs[0x05] |= 0x02; 544 minfo->hw.maven.regs[0x05] |= 0x02;
534 } 545 }
535 } 546 }
536 computeRegs(PMINFO &ACCESS_FBINFO(hw).maven, mt, outd); 547 computeRegs(minfo, &minfo->hw.maven, mt, outd);
537 } else if (mt->mnp < 0) { 548 } else if (mt->mnp < 0) {
538 /* We must program clocks before CRTC2, otherwise interlaced mode 549 /* We must program clocks before CRTC2, otherwise interlaced mode
539 startup may fail */ 550 startup may fail */
540 mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); 551 mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
541 mt->pixclock = g450_mnp2f(PMINFO mt->mnp); 552 mt->pixclock = g450_mnp2f(minfo, mt->mnp);
542 } 553 }
543 dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock); 554 dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock);
544 return 0; 555 return 0;
545} 556}
546 557
547static int matroxfb_g450_program(void* md) { 558static int matroxfb_g450_program(void* md) {
548 MINFO_FROM(md); 559 struct matrox_fb_info *minfo = md;
549 560
550 if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { 561 if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
551 cve2_init_TV(PMINFO &ACCESS_FBINFO(hw).maven); 562 cve2_init_TV(minfo, &minfo->hw.maven);
552 } 563 }
553 return 0; 564 return 0;
554} 565}
@@ -564,11 +575,11 @@ static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
564} 575}
565 576
566static int g450_dvi_compute(void* md, struct my_timming* mt) { 577static int g450_dvi_compute(void* md, struct my_timming* mt) {
567 MINFO_FROM(md); 578 struct matrox_fb_info *minfo = md;
568 579
569 if (mt->mnp < 0) { 580 if (mt->mnp < 0) {
570 mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); 581 mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
571 mt->pixclock = g450_mnp2f(PMINFO mt->mnp); 582 mt->pixclock = g450_mnp2f(minfo, mt->mnp);
572 } 583 }
573 return 0; 584 return 0;
574} 585}
@@ -588,34 +599,36 @@ static struct matrox_altout matroxfb_g450_dvi = {
588 .compute = g450_dvi_compute, 599 .compute = g450_dvi_compute,
589}; 600};
590 601
591void matroxfb_g450_connect(WPMINFO2) { 602void matroxfb_g450_connect(struct matrox_fb_info *minfo)
592 if (ACCESS_FBINFO(devflags.g450dac)) { 603{
593 down_write(&ACCESS_FBINFO(altout.lock)); 604 if (minfo->devflags.g450dac) {
594 tvo_fill_defaults(PMINFO2); 605 down_write(&minfo->altout.lock);
595 ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; 606 tvo_fill_defaults(minfo);
596 ACCESS_FBINFO(outputs[1]).data = MINFO; 607 minfo->outputs[1].src = minfo->outputs[1].default_src;
597 ACCESS_FBINFO(outputs[1]).output = &matroxfb_g450_altout; 608 minfo->outputs[1].data = minfo;
598 ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 609 minfo->outputs[1].output = &matroxfb_g450_altout;
599 ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src; 610 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
600 ACCESS_FBINFO(outputs[2]).data = MINFO; 611 minfo->outputs[2].src = minfo->outputs[2].default_src;
601 ACCESS_FBINFO(outputs[2]).output = &matroxfb_g450_dvi; 612 minfo->outputs[2].data = minfo;
602 ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 613 minfo->outputs[2].output = &matroxfb_g450_dvi;
603 up_write(&ACCESS_FBINFO(altout.lock)); 614 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
615 up_write(&minfo->altout.lock);
604 } 616 }
605} 617}
606 618
607void matroxfb_g450_shutdown(WPMINFO2) { 619void matroxfb_g450_shutdown(struct matrox_fb_info *minfo)
608 if (ACCESS_FBINFO(devflags.g450dac)) { 620{
609 down_write(&ACCESS_FBINFO(altout.lock)); 621 if (minfo->devflags.g450dac) {
610 ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE; 622 down_write(&minfo->altout.lock);
611 ACCESS_FBINFO(outputs[1]).output = NULL; 623 minfo->outputs[1].src = MATROXFB_SRC_NONE;
612 ACCESS_FBINFO(outputs[1]).data = NULL; 624 minfo->outputs[1].output = NULL;
613 ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 625 minfo->outputs[1].data = NULL;
614 ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE; 626 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
615 ACCESS_FBINFO(outputs[2]).output = NULL; 627 minfo->outputs[2].src = MATROXFB_SRC_NONE;
616 ACCESS_FBINFO(outputs[2]).data = NULL; 628 minfo->outputs[2].output = NULL;
617 ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 629 minfo->outputs[2].data = NULL;
618 up_write(&ACCESS_FBINFO(altout.lock)); 630 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
631 up_write(&minfo->altout.lock);
619 } 632 }
620} 633}
621 634
diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/matrox/matroxfb_g450.h
index a0822a6033e5..3a3e654444b8 100644
--- a/drivers/video/matrox/matroxfb_g450.h
+++ b/drivers/video/matrox/matroxfb_g450.h
@@ -4,11 +4,11 @@
4#include "matroxfb_base.h" 4#include "matroxfb_base.h"
5 5
6#ifdef CONFIG_FB_MATROX_G 6#ifdef CONFIG_FB_MATROX_G
7void matroxfb_g450_connect(WPMINFO2); 7void matroxfb_g450_connect(struct matrox_fb_info *minfo);
8void matroxfb_g450_shutdown(WPMINFO2); 8void matroxfb_g450_shutdown(struct matrox_fb_info *minfo);
9#else 9#else
10static inline void matroxfb_g450_connect(WPMINFO2) { }; 10static inline void matroxfb_g450_connect(struct matrox_fb_info *minfo) { };
11static inline void matroxfb_g450_shutdown(WPMINFO2) { }; 11static inline void matroxfb_g450_shutdown(struct matrox_fb_info *minfo) { };
12#endif 12#endif
13 13
14#endif /* __MATROXFB_G450_H__ */ 14#endif /* __MATROXFB_G450_H__ */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 042408a8c631..91af9159111f 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -458,9 +458,9 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat
458 0x00, /* 3E written multiple times */ 458 0x00, /* 3E written multiple times */
459 0x00, /* never written */ 459 0x00, /* never written */
460 }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 }; 460 }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 };
461 MINFO_FROM(md->primary_head); 461 struct matrox_fb_info *minfo = md->primary_head;
462 462
463 if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_PAL) 463 if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_PAL)
464 *data = palregs; 464 *data = palregs;
465 else 465 else
466 *data = ntscregs; 466 *data = ntscregs;
@@ -496,11 +496,11 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat
496 /* Set saturation */ 496 /* Set saturation */
497 { 497 {
498 data->regs[0x20] = 498 data->regs[0x20] =
499 data->regs[0x22] = ACCESS_FBINFO(altout.tvo_params.saturation); 499 data->regs[0x22] = minfo->altout.tvo_params.saturation;
500 } 500 }
501 501
502 /* Set HUE */ 502 /* Set HUE */
503 data->regs[0x25] = ACCESS_FBINFO(altout.tvo_params.hue); 503 data->regs[0x25] = minfo->altout.tvo_params.hue;
504 return; 504 return;
505} 505}
506 506
@@ -741,9 +741,9 @@ static inline int maven_compute_timming(struct maven_data* md,
741 struct mavenregs* m) { 741 struct mavenregs* m) {
742 unsigned int tmpi; 742 unsigned int tmpi;
743 unsigned int a, bv, c; 743 unsigned int a, bv, c;
744 MINFO_FROM(md->primary_head); 744 struct matrox_fb_info *minfo = md->primary_head;
745 745
746 m->mode = ACCESS_FBINFO(outputs[1]).mode; 746 m->mode = minfo->outputs[1].mode;
747 if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) { 747 if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
748 unsigned int lmargin; 748 unsigned int lmargin;
749 unsigned int umargin; 749 unsigned int umargin;
@@ -1132,7 +1132,7 @@ static int maven_get_control (struct maven_data* md,
1132static int maven_out_compute(void* md, struct my_timming* mt) { 1132static int maven_out_compute(void* md, struct my_timming* mt) {
1133#define mdinfo ((struct maven_data*)md) 1133#define mdinfo ((struct maven_data*)md)
1134#define minfo (mdinfo->primary_head) 1134#define minfo (mdinfo->primary_head)
1135 return maven_compute_timming(md, mt, &ACCESS_FBINFO(hw).maven); 1135 return maven_compute_timming(md, mt, &minfo->hw.maven);
1136#undef minfo 1136#undef minfo
1137#undef mdinfo 1137#undef mdinfo
1138} 1138}
@@ -1140,7 +1140,7 @@ static int maven_out_compute(void* md, struct my_timming* mt) {
1140static int maven_out_program(void* md) { 1140static int maven_out_program(void* md) {
1141#define mdinfo ((struct maven_data*)md) 1141#define mdinfo ((struct maven_data*)md)
1142#define minfo (mdinfo->primary_head) 1142#define minfo (mdinfo->primary_head)
1143 return maven_program_timming(md, &ACCESS_FBINFO(hw).maven); 1143 return maven_program_timming(md, &minfo->hw.maven);
1144#undef minfo 1144#undef minfo
1145#undef mdinfo 1145#undef mdinfo
1146} 1146}
@@ -1184,16 +1184,18 @@ static struct matrox_altout maven_altout = {
1184 1184
1185static int maven_init_client(struct i2c_client* clnt) { 1185static int maven_init_client(struct i2c_client* clnt) {
1186 struct maven_data* md = i2c_get_clientdata(clnt); 1186 struct maven_data* md = i2c_get_clientdata(clnt);
1187 MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); 1187 struct matrox_fb_info *minfo = container_of(clnt->adapter,
1188 struct i2c_bit_adapter,
1189 adapter)->minfo;
1188 1190
1189 md->primary_head = MINFO; 1191 md->primary_head = minfo;
1190 md->client = clnt; 1192 md->client = clnt;
1191 down_write(&ACCESS_FBINFO(altout.lock)); 1193 down_write(&minfo->altout.lock);
1192 ACCESS_FBINFO(outputs[1]).output = &maven_altout; 1194 minfo->outputs[1].output = &maven_altout;
1193 ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; 1195 minfo->outputs[1].src = minfo->outputs[1].default_src;
1194 ACCESS_FBINFO(outputs[1]).data = md; 1196 minfo->outputs[1].data = md;
1195 ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 1197 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
1196 up_write(&ACCESS_FBINFO(altout.lock)); 1198 up_write(&minfo->altout.lock);
1197 if (maven_get_reg(clnt, 0xB2) < 0x14) { 1199 if (maven_get_reg(clnt, 0xB2) < 0x14) {
1198 md->version = MGATVO_B; 1200 md->version = MGATVO_B;
1199 /* Tweak some things for this old chip */ 1201 /* Tweak some things for this old chip */
@@ -1218,14 +1220,14 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
1218 struct maven_data* md = i2c_get_clientdata(clnt); 1220 struct maven_data* md = i2c_get_clientdata(clnt);
1219 1221
1220 if (md->primary_head) { 1222 if (md->primary_head) {
1221 MINFO_FROM(md->primary_head); 1223 struct matrox_fb_info *minfo = md->primary_head;
1222 1224
1223 down_write(&ACCESS_FBINFO(altout.lock)); 1225 down_write(&minfo->altout.lock);
1224 ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE; 1226 minfo->outputs[1].src = MATROXFB_SRC_NONE;
1225 ACCESS_FBINFO(outputs[1]).output = NULL; 1227 minfo->outputs[1].output = NULL;
1226 ACCESS_FBINFO(outputs[1]).data = NULL; 1228 minfo->outputs[1].data = NULL;
1227 ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 1229 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
1228 up_write(&ACCESS_FBINFO(altout.lock)); 1230 up_write(&minfo->altout.lock);
1229 md->primary_head = NULL; 1231 md->primary_head = NULL;
1230 } 1232 }
1231 return 0; 1233 return 0;
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 5b5f072fc1a8..9948ca2a3046 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -89,13 +89,15 @@
89#include <linux/interrupt.h> 89#include <linux/interrupt.h>
90#include <linux/matroxfb.h> 90#include <linux/matroxfb.h>
91 91
92void matroxfb_DAC_out(CPMINFO int reg, int val) { 92void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, int val)
93{
93 DBG_REG(__func__) 94 DBG_REG(__func__)
94 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg); 95 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
95 mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val); 96 mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
96} 97}
97 98
98int matroxfb_DAC_in(CPMINFO int reg) { 99int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg)
100{
99 DBG_REG(__func__) 101 DBG_REG(__func__)
100 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg); 102 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
101 return mga_inb(M_RAMDAC_BASE+M_X_DATAREG); 103 return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
@@ -184,13 +186,14 @@ int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int f
184 return bestvco; 186 return bestvco;
185} 187}
186 188
187int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) { 189int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming *m)
190{
188 unsigned int hd, hs, he, hbe, ht; 191 unsigned int hd, hs, he, hbe, ht;
189 unsigned int vd, vs, ve, vt, lc; 192 unsigned int vd, vs, ve, vt, lc;
190 unsigned int wd; 193 unsigned int wd;
191 unsigned int divider; 194 unsigned int divider;
192 int i; 195 int i;
193 struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); 196 struct matrox_hw_state * const hw = &minfo->hw;
194 197
195 DBG(__func__) 198 DBG(__func__)
196 199
@@ -240,7 +243,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
240 /* standard timmings are in 8pixels, but for interleaved we cannot */ 243 /* standard timmings are in 8pixels, but for interleaved we cannot */
241 /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */ 244 /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
242 /* using 16 or more pixels per unit can save us */ 245 /* using 16 or more pixels per unit can save us */
243 divider = ACCESS_FBINFO(curr.final_bppShift); 246 divider = minfo->curr.final_bppShift;
244 while (divider & 3) { 247 while (divider & 3) {
245 hd >>= 1; 248 hd >>= 1;
246 hs >>= 1; 249 hs >>= 1;
@@ -270,7 +273,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
270 if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04)) 273 if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
271 ht++; 274 ht++;
272 hbe = ht; 275 hbe = ht;
273 wd = ACCESS_FBINFO(fbcon).var.xres_virtual * ACCESS_FBINFO(curr.final_bppShift) / 64; 276 wd = minfo->fbcon.var.xres_virtual * minfo->curr.final_bppShift / 64;
274 277
275 hw->CRTCEXT[0] = 0; 278 hw->CRTCEXT[0] = 0;
276 hw->CRTCEXT[5] = 0; 279 hw->CRTCEXT[5] = 0;
@@ -287,7 +290,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
287 ((hs & 0x100) >> 6) | /* sync start */ 290 ((hs & 0x100) >> 6) | /* sync start */
288 (hbe & 0x040); /* end hor. blanking */ 291 (hbe & 0x040); /* end hor. blanking */
289 /* FIXME: Enable vidrst only on G400, and only if TV-out is used */ 292 /* FIXME: Enable vidrst only on G400, and only if TV-out is used */
290 if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) 293 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1)
291 hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */ 294 hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */
292 hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) | 295 hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
293 ((vd & 0x400) >> 8) | /* disp end */ 296 ((vd & 0x400) >> 8) | /* disp end */
@@ -331,9 +334,10 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
331 return 0; 334 return 0;
332}; 335};
333 336
334void matroxfb_vgaHWrestore(WPMINFO2) { 337void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo)
338{
335 int i; 339 int i;
336 struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); 340 struct matrox_hw_state * const hw = &minfo->hw;
337 CRITFLAGS 341 CRITFLAGS
338 342
339 DBG(__func__) 343 DBG(__func__)
@@ -522,7 +526,9 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
522#endif 526#endif
523} 527}
524 528
525static int parse_pins1(WPMINFO const struct matrox_bios* bd) { 529static int parse_pins1(struct matrox_fb_info *minfo,
530 const struct matrox_bios *bd)
531{
526 unsigned int maxdac; 532 unsigned int maxdac;
527 533
528 switch (bd->pins[22]) { 534 switch (bd->pins[22]) {
@@ -533,173 +539,188 @@ static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
533 if (get_unaligned_le16(bd->pins + 24)) { 539 if (get_unaligned_le16(bd->pins + 24)) {
534 maxdac = get_unaligned_le16(bd->pins + 24) * 10; 540 maxdac = get_unaligned_le16(bd->pins + 24) * 10;
535 } 541 }
536 MINFO->limits.pixel.vcomax = maxdac; 542 minfo->limits.pixel.vcomax = maxdac;
537 MINFO->values.pll.system = get_unaligned_le16(bd->pins + 28) ? 543 minfo->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
538 get_unaligned_le16(bd->pins + 28) * 10 : 50000; 544 get_unaligned_le16(bd->pins + 28) * 10 : 50000;
539 /* ignore 4MB, 8MB, module clocks */ 545 /* ignore 4MB, 8MB, module clocks */
540 MINFO->features.pll.ref_freq = 14318; 546 minfo->features.pll.ref_freq = 14318;
541 MINFO->values.reg.mctlwtst = 0x00030101; 547 minfo->values.reg.mctlwtst = 0x00030101;
542 return 0; 548 return 0;
543} 549}
544 550
545static void default_pins1(WPMINFO2) { 551static void default_pins1(struct matrox_fb_info *minfo)
552{
546 /* Millennium */ 553 /* Millennium */
547 MINFO->limits.pixel.vcomax = 220000; 554 minfo->limits.pixel.vcomax = 220000;
548 MINFO->values.pll.system = 50000; 555 minfo->values.pll.system = 50000;
549 MINFO->features.pll.ref_freq = 14318; 556 minfo->features.pll.ref_freq = 14318;
550 MINFO->values.reg.mctlwtst = 0x00030101; 557 minfo->values.reg.mctlwtst = 0x00030101;
551} 558}
552 559
553static int parse_pins2(WPMINFO const struct matrox_bios* bd) { 560static int parse_pins2(struct matrox_fb_info *minfo,
554 MINFO->limits.pixel.vcomax = 561 const struct matrox_bios *bd)
555 MINFO->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000); 562{
556 MINFO->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) | 563 minfo->limits.pixel.vcomax =
564 minfo->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
565 minfo->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
557 ((bd->pins[51] & 0x02) ? 0x00000100 : 0) | 566 ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
558 ((bd->pins[51] & 0x04) ? 0x00010000 : 0) | 567 ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
559 ((bd->pins[51] & 0x08) ? 0x00020000 : 0); 568 ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
560 MINFO->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000); 569 minfo->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
561 MINFO->features.pll.ref_freq = 14318; 570 minfo->features.pll.ref_freq = 14318;
562 return 0; 571 return 0;
563} 572}
564 573
565static void default_pins2(WPMINFO2) { 574static void default_pins2(struct matrox_fb_info *minfo)
575{
566 /* Millennium II, Mystique */ 576 /* Millennium II, Mystique */
567 MINFO->limits.pixel.vcomax = 577 minfo->limits.pixel.vcomax =
568 MINFO->limits.system.vcomax = 230000; 578 minfo->limits.system.vcomax = 230000;
569 MINFO->values.reg.mctlwtst = 0x00030101; 579 minfo->values.reg.mctlwtst = 0x00030101;
570 MINFO->values.pll.system = 50000; 580 minfo->values.pll.system = 50000;
571 MINFO->features.pll.ref_freq = 14318; 581 minfo->features.pll.ref_freq = 14318;
572} 582}
573 583
574static int parse_pins3(WPMINFO const struct matrox_bios* bd) { 584static int parse_pins3(struct matrox_fb_info *minfo,
575 MINFO->limits.pixel.vcomax = 585 const struct matrox_bios *bd)
576 MINFO->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000); 586{
577 MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ? 587 minfo->limits.pixel.vcomax =
588 minfo->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000);
589 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
578 0x01250A21 : get_unaligned_le32(bd->pins + 48); 590 0x01250A21 : get_unaligned_le32(bd->pins + 48);
579 /* memory config */ 591 /* memory config */
580 MINFO->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) | 592 minfo->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) |
581 ((bd->pins[57] << 22) & 0x00C00000) | 593 ((bd->pins[57] << 22) & 0x00C00000) |
582 ((bd->pins[56] << 1) & 0x000001E0) | 594 ((bd->pins[56] << 1) & 0x000001E0) |
583 ( bd->pins[56] & 0x0000000F); 595 ( bd->pins[56] & 0x0000000F);
584 MINFO->values.reg.opt = (bd->pins[54] & 7) << 10; 596 minfo->values.reg.opt = (bd->pins[54] & 7) << 10;
585 MINFO->values.reg.opt2 = bd->pins[58] << 12; 597 minfo->values.reg.opt2 = bd->pins[58] << 12;
586 MINFO->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000; 598 minfo->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000;
587 return 0; 599 return 0;
588} 600}
589 601
590static void default_pins3(WPMINFO2) { 602static void default_pins3(struct matrox_fb_info *minfo)
603{
591 /* G100, G200 */ 604 /* G100, G200 */
592 MINFO->limits.pixel.vcomax = 605 minfo->limits.pixel.vcomax =
593 MINFO->limits.system.vcomax = 230000; 606 minfo->limits.system.vcomax = 230000;
594 MINFO->values.reg.mctlwtst = 0x01250A21; 607 minfo->values.reg.mctlwtst = 0x01250A21;
595 MINFO->values.reg.memrdbk = 0x00000000; 608 minfo->values.reg.memrdbk = 0x00000000;
596 MINFO->values.reg.opt = 0x00000C00; 609 minfo->values.reg.opt = 0x00000C00;
597 MINFO->values.reg.opt2 = 0x00000000; 610 minfo->values.reg.opt2 = 0x00000000;
598 MINFO->features.pll.ref_freq = 27000; 611 minfo->features.pll.ref_freq = 27000;
599} 612}
600 613
601static int parse_pins4(WPMINFO const struct matrox_bios* bd) { 614static int parse_pins4(struct matrox_fb_info *minfo,
602 MINFO->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000; 615 const struct matrox_bios *bd)
603 MINFO->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 38] * 4000; 616{
604 MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71); 617 minfo->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000;
605 MINFO->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) | 618 minfo->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 38] * 4000;
619 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71);
620 minfo->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) |
606 ((bd->pins[87] << 22) & 0x00C00000) | 621 ((bd->pins[87] << 22) & 0x00C00000) |
607 ((bd->pins[86] << 1) & 0x000001E0) | 622 ((bd->pins[86] << 1) & 0x000001E0) |
608 ( bd->pins[86] & 0x0000000F); 623 ( bd->pins[86] & 0x0000000F);
609 MINFO->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) | 624 minfo->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) |
610 ((bd->pins[53] << 22) & 0x10000000) | 625 ((bd->pins[53] << 22) & 0x10000000) |
611 ((bd->pins[53] << 7) & 0x00001C00); 626 ((bd->pins[53] << 7) & 0x00001C00);
612 MINFO->values.reg.opt3 = get_unaligned_le32(bd->pins + 67); 627 minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 67);
613 MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000; 628 minfo->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000;
614 MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000; 629 minfo->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
615 return 0; 630 return 0;
616} 631}
617 632
618static void default_pins4(WPMINFO2) { 633static void default_pins4(struct matrox_fb_info *minfo)
634{
619 /* G400 */ 635 /* G400 */
620 MINFO->limits.pixel.vcomax = 636 minfo->limits.pixel.vcomax =
621 MINFO->limits.system.vcomax = 252000; 637 minfo->limits.system.vcomax = 252000;
622 MINFO->values.reg.mctlwtst = 0x04A450A1; 638 minfo->values.reg.mctlwtst = 0x04A450A1;
623 MINFO->values.reg.memrdbk = 0x000000E7; 639 minfo->values.reg.memrdbk = 0x000000E7;
624 MINFO->values.reg.opt = 0x10000400; 640 minfo->values.reg.opt = 0x10000400;
625 MINFO->values.reg.opt3 = 0x0190A419; 641 minfo->values.reg.opt3 = 0x0190A419;
626 MINFO->values.pll.system = 200000; 642 minfo->values.pll.system = 200000;
627 MINFO->features.pll.ref_freq = 27000; 643 minfo->features.pll.ref_freq = 27000;
628} 644}
629 645
630static int parse_pins5(WPMINFO const struct matrox_bios* bd) { 646static int parse_pins5(struct matrox_fb_info *minfo,
647 const struct matrox_bios *bd)
648{
631 unsigned int mult; 649 unsigned int mult;
632 650
633 mult = bd->pins[4]?8000:6000; 651 mult = bd->pins[4]?8000:6000;
634 652
635 MINFO->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult; 653 minfo->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult;
636 MINFO->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 36] * mult; 654 minfo->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 36] * mult;
637 MINFO->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? MINFO->limits.system.vcomax : bd->pins[ 37] * mult; 655 minfo->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax : bd->pins[ 37] * mult;
638 MINFO->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult; 656 minfo->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult;
639 MINFO->limits.system.vcomin = (bd->pins[121] == 0xFF) ? MINFO->limits.pixel.vcomin : bd->pins[121] * mult; 657 minfo->limits.system.vcomin = (bd->pins[121] == 0xFF) ? minfo->limits.pixel.vcomin : bd->pins[121] * mult;
640 MINFO->limits.video.vcomin = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult; 658 minfo->limits.video.vcomin = (bd->pins[122] == 0xFF) ? minfo->limits.system.vcomin : bd->pins[122] * mult;
641 MINFO->values.pll.system = 659 minfo->values.pll.system =
642 MINFO->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000; 660 minfo->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000;
643 MINFO->values.reg.opt = get_unaligned_le32(bd->pins + 48); 661 minfo->values.reg.opt = get_unaligned_le32(bd->pins + 48);
644 MINFO->values.reg.opt2 = get_unaligned_le32(bd->pins + 52); 662 minfo->values.reg.opt2 = get_unaligned_le32(bd->pins + 52);
645 MINFO->values.reg.opt3 = get_unaligned_le32(bd->pins + 94); 663 minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 94);
646 MINFO->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98); 664 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98);
647 MINFO->values.reg.memmisc = get_unaligned_le32(bd->pins + 102); 665 minfo->values.reg.memmisc = get_unaligned_le32(bd->pins + 102);
648 MINFO->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106); 666 minfo->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106);
649 MINFO->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000; 667 minfo->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000;
650 MINFO->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20; 668 minfo->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20;
651 MINFO->values.memory.dll = (bd->pins[115] & 0x02) != 0; 669 minfo->values.memory.dll = (bd->pins[115] & 0x02) != 0;
652 MINFO->values.memory.emrswen = (bd->pins[115] & 0x01) != 0; 670 minfo->values.memory.emrswen = (bd->pins[115] & 0x01) != 0;
653 MINFO->values.reg.maccess = MINFO->values.memory.emrswen ? 0x00004000 : 0x00000000; 671 minfo->values.reg.maccess = minfo->values.memory.emrswen ? 0x00004000 : 0x00000000;
654 if (bd->pins[115] & 4) { 672 if (bd->pins[115] & 4) {
655 MINFO->values.reg.mctlwtst_core = MINFO->values.reg.mctlwtst; 673 minfo->values.reg.mctlwtst_core = minfo->values.reg.mctlwtst;
656 } else { 674 } else {
657 u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 }; 675 u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 };
658 MINFO->values.reg.mctlwtst_core = (MINFO->values.reg.mctlwtst & ~7) | 676 minfo->values.reg.mctlwtst_core = (minfo->values.reg.mctlwtst & ~7) |
659 wtst_xlat[MINFO->values.reg.mctlwtst & 7]; 677 wtst_xlat[minfo->values.reg.mctlwtst & 7];
660 } 678 }
661 MINFO->max_pixel_clock_panellink = bd->pins[47] * 4000; 679 minfo->max_pixel_clock_panellink = bd->pins[47] * 4000;
662 return 0; 680 return 0;
663} 681}
664 682
665static void default_pins5(WPMINFO2) { 683static void default_pins5(struct matrox_fb_info *minfo)
684{
666 /* Mine 16MB G450 with SDRAM DDR */ 685 /* Mine 16MB G450 with SDRAM DDR */
667 MINFO->limits.pixel.vcomax = 686 minfo->limits.pixel.vcomax =
668 MINFO->limits.system.vcomax = 687 minfo->limits.system.vcomax =
669 MINFO->limits.video.vcomax = 600000; 688 minfo->limits.video.vcomax = 600000;
670 MINFO->limits.pixel.vcomin = 689 minfo->limits.pixel.vcomin =
671 MINFO->limits.system.vcomin = 690 minfo->limits.system.vcomin =
672 MINFO->limits.video.vcomin = 256000; 691 minfo->limits.video.vcomin = 256000;
673 MINFO->values.pll.system = 692 minfo->values.pll.system =
674 MINFO->values.pll.video = 284000; 693 minfo->values.pll.video = 284000;
675 MINFO->values.reg.opt = 0x404A1160; 694 minfo->values.reg.opt = 0x404A1160;
676 MINFO->values.reg.opt2 = 0x0000AC00; 695 minfo->values.reg.opt2 = 0x0000AC00;
677 MINFO->values.reg.opt3 = 0x0090A409; 696 minfo->values.reg.opt3 = 0x0090A409;
678 MINFO->values.reg.mctlwtst_core = 697 minfo->values.reg.mctlwtst_core =
679 MINFO->values.reg.mctlwtst = 0x0C81462B; 698 minfo->values.reg.mctlwtst = 0x0C81462B;
680 MINFO->values.reg.memmisc = 0x80000004; 699 minfo->values.reg.memmisc = 0x80000004;
681 MINFO->values.reg.memrdbk = 0x01001103; 700 minfo->values.reg.memrdbk = 0x01001103;
682 MINFO->features.pll.ref_freq = 27000; 701 minfo->features.pll.ref_freq = 27000;
683 MINFO->values.memory.ddr = 1; 702 minfo->values.memory.ddr = 1;
684 MINFO->values.memory.dll = 1; 703 minfo->values.memory.dll = 1;
685 MINFO->values.memory.emrswen = 1; 704 minfo->values.memory.emrswen = 1;
686 MINFO->values.reg.maccess = 0x00004000; 705 minfo->values.reg.maccess = 0x00004000;
687} 706}
688 707
689static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) { 708static int matroxfb_set_limits(struct matrox_fb_info *minfo,
709 const struct matrox_bios *bd)
710{
690 unsigned int pins_version; 711 unsigned int pins_version;
691 static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 }; 712 static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
692 713
693 switch (ACCESS_FBINFO(chip)) { 714 switch (minfo->chip) {
694 case MGA_2064: default_pins1(PMINFO2); break; 715 case MGA_2064: default_pins1(minfo); break;
695 case MGA_2164: 716 case MGA_2164:
696 case MGA_1064: 717 case MGA_1064:
697 case MGA_1164: default_pins2(PMINFO2); break; 718 case MGA_1164: default_pins2(minfo); break;
698 case MGA_G100: 719 case MGA_G100:
699 case MGA_G200: default_pins3(PMINFO2); break; 720 case MGA_G200: default_pins3(minfo); break;
700 case MGA_G400: default_pins4(PMINFO2); break; 721 case MGA_G400: default_pins4(minfo); break;
701 case MGA_G450: 722 case MGA_G450:
702 case MGA_G550: default_pins5(PMINFO2); break; 723 case MGA_G550: default_pins5(minfo); break;
703 } 724 }
704 if (!bd->bios_valid) { 725 if (!bd->bios_valid) {
705 printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n"); 726 printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n");
@@ -724,38 +745,39 @@ static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) {
724 } 745 }
725 switch (pins_version) { 746 switch (pins_version) {
726 case 1: 747 case 1:
727 return parse_pins1(PMINFO bd); 748 return parse_pins1(minfo, bd);
728 case 2: 749 case 2:
729 return parse_pins2(PMINFO bd); 750 return parse_pins2(minfo, bd);
730 case 3: 751 case 3:
731 return parse_pins3(PMINFO bd); 752 return parse_pins3(minfo, bd);
732 case 4: 753 case 4:
733 return parse_pins4(PMINFO bd); 754 return parse_pins4(minfo, bd);
734 case 5: 755 case 5:
735 return parse_pins5(PMINFO bd); 756 return parse_pins5(minfo, bd);
736 default: 757 default:
737 printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version); 758 printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version);
738 return -1; 759 return -1;
739 } 760 }
740} 761}
741 762
742void matroxfb_read_pins(WPMINFO2) { 763void matroxfb_read_pins(struct matrox_fb_info *minfo)
764{
743 u32 opt; 765 u32 opt;
744 u32 biosbase; 766 u32 biosbase;
745 u32 fbbase; 767 u32 fbbase;
746 struct pci_dev* pdev = ACCESS_FBINFO(pcidev); 768 struct pci_dev *pdev = minfo->pcidev;
747 769
748 memset(&ACCESS_FBINFO(bios), 0, sizeof(ACCESS_FBINFO(bios))); 770 memset(&minfo->bios, 0, sizeof(minfo->bios));
749 pci_read_config_dword(pdev, PCI_OPTION_REG, &opt); 771 pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
750 pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM); 772 pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
751 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase); 773 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
752 pci_read_config_dword(pdev, ACCESS_FBINFO(devflags.fbResource), &fbbase); 774 pci_read_config_dword(pdev, minfo->devflags.fbResource, &fbbase);
753 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE); 775 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
754 parse_bios(vaddr_va(ACCESS_FBINFO(video).vbase), &ACCESS_FBINFO(bios)); 776 parse_bios(vaddr_va(minfo->video.vbase), &minfo->bios);
755 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase); 777 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
756 pci_write_config_dword(pdev, PCI_OPTION_REG, opt); 778 pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
757#ifdef CONFIG_X86 779#ifdef CONFIG_X86
758 if (!ACCESS_FBINFO(bios).bios_valid) { 780 if (!minfo->bios.bios_valid) {
759 unsigned char __iomem* b; 781 unsigned char __iomem* b;
760 782
761 b = ioremap(0x000C0000, 65536); 783 b = ioremap(0x000C0000, 65536);
@@ -769,25 +791,21 @@ void matroxfb_read_pins(WPMINFO2) {
769 printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n", 791 printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n",
770 ven, dev, pdev->vendor, pdev->device); 792 ven, dev, pdev->vendor, pdev->device);
771 } else { 793 } else {
772 parse_bios(b, &ACCESS_FBINFO(bios)); 794 parse_bios(b, &minfo->bios);
773 } 795 }
774 iounmap(b); 796 iounmap(b);
775 } 797 }
776 } 798 }
777#endif 799#endif
778 matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios)); 800 matroxfb_set_limits(minfo, &minfo->bios);
779 printk(KERN_INFO "PInS memtype = %u\n", 801 printk(KERN_INFO "PInS memtype = %u\n",
780 (ACCESS_FBINFO(values).reg.opt & 0x1C00) >> 10); 802 (minfo->values.reg.opt & 0x1C00) >> 10);
781} 803}
782 804
783EXPORT_SYMBOL(matroxfb_DAC_in); 805EXPORT_SYMBOL(matroxfb_DAC_in);
784EXPORT_SYMBOL(matroxfb_DAC_out); 806EXPORT_SYMBOL(matroxfb_DAC_out);
785EXPORT_SYMBOL(matroxfb_var2my); 807EXPORT_SYMBOL(matroxfb_var2my);
786EXPORT_SYMBOL(matroxfb_PLL_calcclock); 808EXPORT_SYMBOL(matroxfb_PLL_calcclock);
787#ifndef CONFIG_FB_MATROX_MULTIHEAD
788struct matrox_fb_info matroxfb_global_mxinfo;
789EXPORT_SYMBOL(matroxfb_global_mxinfo);
790#endif
791EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */ 809EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */
792EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */ 810EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */
793EXPORT_SYMBOL(matroxfb_read_pins); 811EXPORT_SYMBOL(matroxfb_read_pins);
diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/matrox/matroxfb_misc.h
index cb62cc0ead96..351c823f1f74 100644
--- a/drivers/video/matrox/matroxfb_misc.h
+++ b/drivers/video/matrox/matroxfb_misc.h
@@ -6,13 +6,16 @@
6/* also for modules */ 6/* also for modules */
7int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax, 7int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
8 unsigned int* in, unsigned int* feed, unsigned int* post); 8 unsigned int* in, unsigned int* feed, unsigned int* post);
9static inline int PLL_calcclock(CPMINFO unsigned int freq, unsigned int fmax, 9static inline int PLL_calcclock(const struct matrox_fb_info *minfo,
10 unsigned int* in, unsigned int* feed, unsigned int* post) { 10 unsigned int freq, unsigned int fmax,
11 return matroxfb_PLL_calcclock(&ACCESS_FBINFO(features.pll), freq, fmax, in, feed, post); 11 unsigned int *in, unsigned int *feed,
12 unsigned int *post)
13{
14 return matroxfb_PLL_calcclock(&minfo->features.pll, freq, fmax, in, feed, post);
12} 15}
13 16
14int matroxfb_vgaHWinit(WPMINFO struct my_timming* m); 17int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming* m);
15void matroxfb_vgaHWrestore(WPMINFO2); 18void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo);
16void matroxfb_read_pins(WPMINFO2); 19void matroxfb_read_pins(struct matrox_fb_info *minfo);
17 20
18#endif /* __MATROXFB_MISC_H__ */ 21#endif /* __MATROXFB_MISC_H__ */
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
new file mode 100644
index 000000000000..802d6ae523fb
--- /dev/null
+++ b/drivers/video/msm/Makefile
@@ -0,0 +1,19 @@
1
2# core framebuffer
3#
4obj-y := msm_fb.o
5
6# MDP DMA/PPP engine
7#
8obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
9
10# MDDI interface
11#
12obj-y += mddi.o
13
14# MDDI client/panel drivers
15#
16obj-y += mddi_client_dummy.o
17obj-y += mddi_client_toshiba.o
18obj-y += mddi_client_nt35399.o
19
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
new file mode 100644
index 000000000000..474421fe79a6
--- /dev/null
+++ b/drivers/video/msm/mddi.c
@@ -0,0 +1,827 @@
1/*
2 * MSM MDDI Transport
3 *
4 * Copyright (C) 2007 Google Incorporated
5 * Copyright (C) 2007 QUALCOMM Incorporated
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/dma-mapping.h>
21#include <linux/interrupt.h>
22#include <linux/platform_device.h>
23#include <linux/delay.h>
24#include <linux/spinlock.h>
25#include <linux/clk.h>
26#include <linux/io.h>
27#include <linux/sched.h>
28#include <mach/msm_iomap.h>
29#include <mach/irqs.h>
30#include <mach/board.h>
31#include <mach/msm_fb.h>
32#include "mddi_hw.h"
33
34#define FLAG_DISABLE_HIBERNATION 0x0001
35#define FLAG_HAVE_CAPS 0x0002
36#define FLAG_HAS_VSYNC_IRQ 0x0004
37#define FLAG_HAVE_STATUS 0x0008
38
39#define CMD_GET_CLIENT_CAP 0x0601
40#define CMD_GET_CLIENT_STATUS 0x0602
41
42union mddi_rev {
43 unsigned char raw[MDDI_REV_BUFFER_SIZE];
44 struct mddi_rev_packet hdr;
45 struct mddi_client_status status;
46 struct mddi_client_caps caps;
47 struct mddi_register_access reg;
48};
49
50struct reg_read_info {
51 struct completion done;
52 uint32_t reg;
53 uint32_t status;
54 uint32_t result;
55};
56
57struct mddi_info {
58 uint16_t flags;
59 uint16_t version;
60 char __iomem *base;
61 int irq;
62 struct clk *clk;
63 struct msm_mddi_client_data client_data;
64
65 /* buffer for rev encap packets */
66 void *rev_data;
67 dma_addr_t rev_addr;
68 struct mddi_llentry *reg_write_data;
69 dma_addr_t reg_write_addr;
70 struct mddi_llentry *reg_read_data;
71 dma_addr_t reg_read_addr;
72 size_t rev_data_curr;
73
74 spinlock_t int_lock;
75 uint32_t int_enable;
76 uint32_t got_int;
77 wait_queue_head_t int_wait;
78
79 struct mutex reg_write_lock;
80 struct mutex reg_read_lock;
81 struct reg_read_info *reg_read;
82
83 struct mddi_client_caps caps;
84 struct mddi_client_status status;
85
86 void (*power_client)(struct msm_mddi_client_data *, int);
87
88 /* client device published to bind us to the
89 * appropriate mddi_client driver
90 */
91 char client_name[20];
92
93 struct platform_device client_pdev;
94};
95
96static void mddi_init_rev_encap(struct mddi_info *mddi);
97
98#define mddi_readl(r) readl(mddi->base + (MDDI_##r))
99#define mddi_writel(v, r) writel((v), mddi->base + (MDDI_##r))
100
101void mddi_activate_link(struct msm_mddi_client_data *cdata)
102{
103 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
104 client_data);
105
106 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
107}
108
109static void mddi_handle_link_list_done(struct mddi_info *mddi)
110{
111}
112
113static void mddi_reset_rev_encap_ptr(struct mddi_info *mddi)
114{
115 printk(KERN_INFO "mddi: resetting rev ptr\n");
116 mddi->rev_data_curr = 0;
117 mddi_writel(mddi->rev_addr, REV_PTR);
118 mddi_writel(mddi->rev_addr, REV_PTR);
119 mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
120}
121
122static void mddi_handle_rev_data(struct mddi_info *mddi, union mddi_rev *rev)
123{
124 int i;
125 struct reg_read_info *ri;
126
127 if ((rev->hdr.length <= MDDI_REV_BUFFER_SIZE - 2) &&
128 (rev->hdr.length >= sizeof(struct mddi_rev_packet) - 2)) {
129
130 switch (rev->hdr.type) {
131 case TYPE_CLIENT_CAPS:
132 memcpy(&mddi->caps, &rev->caps,
133 sizeof(struct mddi_client_caps));
134 mddi->flags |= FLAG_HAVE_CAPS;
135 wake_up(&mddi->int_wait);
136 break;
137 case TYPE_CLIENT_STATUS:
138 memcpy(&mddi->status, &rev->status,
139 sizeof(struct mddi_client_status));
140 mddi->flags |= FLAG_HAVE_STATUS;
141 wake_up(&mddi->int_wait);
142 break;
143 case TYPE_REGISTER_ACCESS:
144 ri = mddi->reg_read;
145 if (ri == 0) {
146 printk(KERN_INFO "rev: got reg %x = %x without "
147 " pending read\n",
148 rev->reg.register_address,
149 rev->reg.register_data_list);
150 break;
151 }
152 if (ri->reg != rev->reg.register_address) {
153 printk(KERN_INFO "rev: got reg %x = %x for "
154 "wrong register, expected "
155 "%x\n",
156 rev->reg.register_address,
157 rev->reg.register_data_list, ri->reg);
158 break;
159 }
160 mddi->reg_read = NULL;
161 ri->status = 0;
162 ri->result = rev->reg.register_data_list;
163 complete(&ri->done);
164 break;
165 default:
166 printk(KERN_INFO "rev: unknown reverse packet: "
167 "len=%04x type=%04x CURR_REV_PTR=%x\n",
168 rev->hdr.length, rev->hdr.type,
169 mddi_readl(CURR_REV_PTR));
170 for (i = 0; i < rev->hdr.length + 2; i++) {
171 if ((i % 16) == 0)
172 printk(KERN_INFO "\n");
173 printk(KERN_INFO " %02x", rev->raw[i]);
174 }
175 printk(KERN_INFO "\n");
176 mddi_reset_rev_encap_ptr(mddi);
177 }
178 } else {
179 printk(KERN_INFO "bad rev length, %d, CURR_REV_PTR %x\n",
180 rev->hdr.length, mddi_readl(CURR_REV_PTR));
181 mddi_reset_rev_encap_ptr(mddi);
182 }
183}
184
185static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
186
187static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
188{
189 union mddi_rev *rev = mddi->rev_data;
190 uint32_t rev_data_count;
191 uint32_t rev_crc_err_count;
192 int i;
193 struct reg_read_info *ri;
194 size_t prev_offset;
195 uint16_t length;
196
197 union mddi_rev *crev = mddi->rev_data + mddi->rev_data_curr;
198
199 /* clear the interrupt */
200 mddi_writel(MDDI_INT_REV_DATA_AVAIL, INT);
201 rev_data_count = mddi_readl(REV_PKT_CNT);
202 rev_crc_err_count = mddi_readl(REV_CRC_ERR);
203 if (rev_data_count > 1)
204 printk(KERN_INFO "rev_data_count %d\n", rev_data_count);
205
206 if (rev_crc_err_count) {
207 printk(KERN_INFO "rev_crc_err_count %d, INT %x\n",
208 rev_crc_err_count, mddi_readl(INT));
209 ri = mddi->reg_read;
210 if (ri == 0) {
211 printk(KERN_INFO "rev: got crc error without pending "
212 "read\n");
213 } else {
214 mddi->reg_read = NULL;
215 ri->status = -EIO;
216 ri->result = -1;
217 complete(&ri->done);
218 }
219 }
220
221 if (rev_data_count == 0)
222 return;
223
224 prev_offset = mddi->rev_data_curr;
225
226 length = *((uint8_t *)mddi->rev_data + mddi->rev_data_curr);
227 mddi->rev_data_curr++;
228 if (mddi->rev_data_curr == MDDI_REV_BUFFER_SIZE)
229 mddi->rev_data_curr = 0;
230 length += *((uint8_t *)mddi->rev_data + mddi->rev_data_curr) << 8;
231 mddi->rev_data_curr += 1 + length;
232 if (mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE)
233 mddi->rev_data_curr =
234 mddi->rev_data_curr % MDDI_REV_BUFFER_SIZE;
235
236 if (length > MDDI_REV_BUFFER_SIZE - 2) {
237 printk(KERN_INFO "mddi: rev data length greater than buffer"
238 "size\n");
239 mddi_reset_rev_encap_ptr(mddi);
240 return;
241 }
242
243 if (prev_offset + 2 + length >= MDDI_REV_BUFFER_SIZE) {
244 union mddi_rev tmprev;
245 size_t rem = MDDI_REV_BUFFER_SIZE - prev_offset;
246 memcpy(&tmprev.raw[0], mddi->rev_data + prev_offset, rem);
247 memcpy(&tmprev.raw[rem], mddi->rev_data, 2 + length - rem);
248 mddi_handle_rev_data(mddi, &tmprev);
249 } else {
250 mddi_handle_rev_data(mddi, crev);
251 }
252
253 if (prev_offset < MDDI_REV_BUFFER_SIZE / 2 &&
254 mddi->rev_data_curr >= MDDI_REV_BUFFER_SIZE / 2) {
255 mddi_writel(mddi->rev_addr, REV_PTR);
256 }
257}
258
259static irqreturn_t mddi_isr(int irq, void *data)
260{
261 struct msm_mddi_client_data *cdata = data;
262 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
263 client_data);
264 uint32_t active, status;
265
266 spin_lock(&mddi->int_lock);
267
268 active = mddi_readl(INT);
269 status = mddi_readl(STAT);
270
271 mddi_writel(active, INT);
272
273 /* ignore any interrupts we have disabled */
274 active &= mddi->int_enable;
275
276 mddi->got_int |= active;
277 wake_up(&mddi->int_wait);
278
279 if (active & MDDI_INT_PRI_LINK_LIST_DONE) {
280 mddi->int_enable &= (~MDDI_INT_PRI_LINK_LIST_DONE);
281 mddi_handle_link_list_done(mddi);
282 }
283 if (active & MDDI_INT_REV_DATA_AVAIL)
284 mddi_handle_rev_data_avail(mddi);
285
286 if (active & ~MDDI_INT_NEED_CLEAR)
287 mddi->int_enable &= ~(active & ~MDDI_INT_NEED_CLEAR);
288
289 if (active & MDDI_INT_LINK_ACTIVE) {
290 mddi->int_enable &= (~MDDI_INT_LINK_ACTIVE);
291 mddi->int_enable |= MDDI_INT_IN_HIBERNATION;
292 }
293
294 if (active & MDDI_INT_IN_HIBERNATION) {
295 mddi->int_enable &= (~MDDI_INT_IN_HIBERNATION);
296 mddi->int_enable |= MDDI_INT_LINK_ACTIVE;
297 }
298
299 mddi_writel(mddi->int_enable, INTEN);
300 spin_unlock(&mddi->int_lock);
301
302 return IRQ_HANDLED;
303}
304
305static long mddi_wait_interrupt_timeout(struct mddi_info *mddi,
306 uint32_t intmask, int timeout)
307{
308 unsigned long irq_flags;
309
310 spin_lock_irqsave(&mddi->int_lock, irq_flags);
311 mddi->got_int &= ~intmask;
312 mddi->int_enable |= intmask;
313 mddi_writel(mddi->int_enable, INTEN);
314 spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
315 return wait_event_timeout(mddi->int_wait, mddi->got_int & intmask,
316 timeout);
317}
318
319static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask)
320{
321 if (mddi_wait_interrupt_timeout(mddi, intmask, HZ/10) == 0)
322 printk(KERN_INFO KERN_ERR "mddi_wait_interrupt %d, timeout "
323 "waiting for %x, INT = %x, STAT = %x gotint = %x\n",
324 current->pid, intmask, mddi_readl(INT), mddi_readl(STAT),
325 mddi->got_int);
326}
327
328static void mddi_init_rev_encap(struct mddi_info *mddi)
329{
330 memset(mddi->rev_data, 0xee, MDDI_REV_BUFFER_SIZE);
331 mddi_writel(mddi->rev_addr, REV_PTR);
332 mddi_writel(MDDI_CMD_FORCE_NEW_REV_PTR, CMD);
333 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
334}
335
336void mddi_set_auto_hibernate(struct msm_mddi_client_data *cdata, int on)
337{
338 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
339 client_data);
340 mddi_writel(MDDI_CMD_POWERDOWN, CMD);
341 mddi_wait_interrupt(mddi, MDDI_INT_IN_HIBERNATION);
342 mddi_writel(MDDI_CMD_HIBERNATE | !!on, CMD);
343 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
344}
345
346
347static uint16_t mddi_init_registers(struct mddi_info *mddi)
348{
349 mddi_writel(0x0001, VERSION);
350 mddi_writel(MDDI_HOST_BYTES_PER_SUBFRAME, BPS);
351 mddi_writel(0x0003, SPM); /* subframes per media */
352 mddi_writel(0x0005, TA1_LEN);
353 mddi_writel(MDDI_HOST_TA2_LEN, TA2_LEN);
354 mddi_writel(0x0096, DRIVE_HI);
355 /* 0x32 normal, 0x50 for Toshiba display */
356 mddi_writel(0x0050, DRIVE_LO);
357 mddi_writel(0x003C, DISP_WAKE); /* wakeup counter */
358 mddi_writel(MDDI_HOST_REV_RATE_DIV, REV_RATE_DIV);
359
360 mddi_writel(MDDI_REV_BUFFER_SIZE, REV_SIZE);
361 mddi_writel(MDDI_MAX_REV_PKT_SIZE, REV_ENCAP_SZ);
362
363 /* disable periodic rev encap */
364 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP, CMD);
365 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
366
367 if (mddi_readl(PAD_CTL) == 0) {
368 /* If we are turning on band gap, need to wait 5us before
369 * turning on the rest of the PAD */
370 mddi_writel(0x08000, PAD_CTL);
371 udelay(5);
372 }
373
374 /* Recommendation from PAD hw team */
375 mddi_writel(0xa850f, PAD_CTL);
376
377
378 /* Need an even number for counts */
379 mddi_writel(0x60006, DRIVER_START_CNT);
380
381 mddi_set_auto_hibernate(&mddi->client_data, 0);
382
383 mddi_writel(MDDI_CMD_DISP_IGNORE, CMD);
384 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
385
386 mddi_init_rev_encap(mddi);
387 return mddi_readl(CORE_VER) & 0xffff;
388}
389
390static void mddi_suspend(struct msm_mddi_client_data *cdata)
391{
392 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
393 client_data);
394 /* turn off the client */
395 if (mddi->power_client)
396 mddi->power_client(&mddi->client_data, 0);
397 /* turn off the link */
398 mddi_writel(MDDI_CMD_RESET, CMD);
399 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
400 /* turn off the clock */
401 clk_disable(mddi->clk);
402}
403
404static void mddi_resume(struct msm_mddi_client_data *cdata)
405{
406 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
407 client_data);
408 mddi_set_auto_hibernate(&mddi->client_data, 0);
409 /* turn on the client */
410 if (mddi->power_client)
411 mddi->power_client(&mddi->client_data, 1);
412 /* turn on the clock */
413 clk_enable(mddi->clk);
414 /* set up the local registers */
415 mddi->rev_data_curr = 0;
416 mddi_init_registers(mddi);
417 mddi_writel(mddi->int_enable, INTEN);
418 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
419 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
420 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
421 mddi_set_auto_hibernate(&mddi->client_data, 1);
422}
423
424static int __init mddi_get_client_caps(struct mddi_info *mddi)
425{
426 int i, j;
427
428 /* clear any stale interrupts */
429 mddi_writel(0xffffffff, INT);
430
431 mddi->int_enable = MDDI_INT_LINK_ACTIVE |
432 MDDI_INT_IN_HIBERNATION |
433 MDDI_INT_PRI_LINK_LIST_DONE |
434 MDDI_INT_REV_DATA_AVAIL |
435 MDDI_INT_REV_OVERFLOW |
436 MDDI_INT_REV_OVERWRITE |
437 MDDI_INT_RTD_FAILURE;
438 mddi_writel(mddi->int_enable, INTEN);
439
440 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
441 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
442
443 for (j = 0; j < 3; j++) {
444 /* the toshiba vga panel does not respond to get
445 * caps unless you SEND_RTD, but the first SEND_RTD
446 * will fail...
447 */
448 for (i = 0; i < 4; i++) {
449 uint32_t stat;
450
451 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
452 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
453 stat = mddi_readl(STAT);
454 printk(KERN_INFO "mddi cmd send rtd: int %x, stat %x, "
455 "rtd val %x\n", mddi_readl(INT), stat,
456 mddi_readl(RTD_VAL));
457 if ((stat & MDDI_STAT_RTD_MEAS_FAIL) == 0)
458 break;
459 msleep(1);
460 }
461
462 mddi_writel(CMD_GET_CLIENT_CAP, CMD);
463 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
464 wait_event_timeout(mddi->int_wait, mddi->flags & FLAG_HAVE_CAPS,
465 HZ / 100);
466
467 if (mddi->flags & FLAG_HAVE_CAPS)
468 break;
469 printk(KERN_INFO KERN_ERR "mddi_init, timeout waiting for "
470 "caps\n");
471 }
472 return mddi->flags & FLAG_HAVE_CAPS;
473}
474
475/* link must be active when this is called */
476int mddi_check_status(struct mddi_info *mddi)
477{
478 int ret = -1, retry = 3;
479 mutex_lock(&mddi->reg_read_lock);
480 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
481 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
482
483 do {
484 mddi->flags &= ~FLAG_HAVE_STATUS;
485 mddi_writel(CMD_GET_CLIENT_STATUS, CMD);
486 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
487 wait_event_timeout(mddi->int_wait,
488 mddi->flags & FLAG_HAVE_STATUS,
489 HZ / 100);
490
491 if (mddi->flags & FLAG_HAVE_STATUS) {
492 if (mddi->status.crc_error_count)
493 printk(KERN_INFO "mddi status: crc_error "
494 "count: %d\n",
495 mddi->status.crc_error_count);
496 else
497 ret = 0;
498 break;
499 } else
500 printk(KERN_INFO "mddi status: failed to get client "
501 "status\n");
502 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
503 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
504 } while (--retry);
505
506 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
507 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
508 mutex_unlock(&mddi->reg_read_lock);
509 return ret;
510}
511
512
513void mddi_remote_write(struct msm_mddi_client_data *cdata, uint32_t val,
514 uint32_t reg)
515{
516 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
517 client_data);
518 struct mddi_llentry *ll;
519 struct mddi_register_access *ra;
520
521 mutex_lock(&mddi->reg_write_lock);
522
523 ll = mddi->reg_write_data;
524
525 ra = &(ll->u.r);
526 ra->length = 14 + 4;
527 ra->type = TYPE_REGISTER_ACCESS;
528 ra->client_id = 0;
529 ra->read_write_info = MDDI_WRITE | 1;
530 ra->crc16 = 0;
531
532 ra->register_address = reg;
533 ra->register_data_list = val;
534
535 ll->flags = 1;
536 ll->header_count = 14;
537 ll->data_count = 4;
538 ll->data = mddi->reg_write_addr + offsetof(struct mddi_llentry,
539 u.r.register_data_list);
540 ll->next = 0;
541 ll->reserved = 0;
542
543 mddi_writel(mddi->reg_write_addr, PRI_PTR);
544
545 mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
546 mutex_unlock(&mddi->reg_write_lock);
547}
548
549uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
550{
551 struct mddi_info *mddi = container_of(cdata, struct mddi_info,
552 client_data);
553 struct mddi_llentry *ll;
554 struct mddi_register_access *ra;
555 struct reg_read_info ri;
556 unsigned s;
557 int retry_count = 2;
558 unsigned long irq_flags;
559
560 mutex_lock(&mddi->reg_read_lock);
561
562 ll = mddi->reg_read_data;
563
564 ra = &(ll->u.r);
565 ra->length = 14;
566 ra->type = TYPE_REGISTER_ACCESS;
567 ra->client_id = 0;
568 ra->read_write_info = MDDI_READ | 1;
569 ra->crc16 = 0;
570
571 ra->register_address = reg;
572
573 ll->flags = 0x11;
574 ll->header_count = 14;
575 ll->data_count = 0;
576 ll->data = 0;
577 ll->next = 0;
578 ll->reserved = 0;
579
580 s = mddi_readl(STAT);
581
582 ri.reg = reg;
583 ri.status = -1;
584
585 do {
586 init_completion(&ri.done);
587 mddi->reg_read = &ri;
588 mddi_writel(mddi->reg_read_addr, PRI_PTR);
589
590 mddi_wait_interrupt(mddi, MDDI_INT_PRI_LINK_LIST_DONE);
591
592 /* Enable Periodic Reverse Encapsulation. */
593 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 1, CMD);
594 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
595 if (wait_for_completion_timeout(&ri.done, HZ/10) == 0 &&
596 !ri.done.done) {
597 printk(KERN_INFO "mddi_remote_read(%x) timeout "
598 "(%d %d %d)\n",
599 reg, ri.status, ri.result, ri.done.done);
600 spin_lock_irqsave(&mddi->int_lock, irq_flags);
601 mddi->reg_read = NULL;
602 spin_unlock_irqrestore(&mddi->int_lock, irq_flags);
603 ri.status = -1;
604 ri.result = -1;
605 }
606 if (ri.status == 0)
607 break;
608
609 mddi_writel(MDDI_CMD_SEND_RTD, CMD);
610 mddi_writel(MDDI_CMD_LINK_ACTIVE, CMD);
611 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
612 printk(KERN_INFO "mddi_remote_read: failed, sent "
613 "MDDI_CMD_SEND_RTD: int %x, stat %x, rtd val %x "
614 "curr_rev_ptr %x\n", mddi_readl(INT), mddi_readl(STAT),
615 mddi_readl(RTD_VAL), mddi_readl(CURR_REV_PTR));
616 } while (retry_count-- > 0);
617 /* Disable Periodic Reverse Encapsulation. */
618 mddi_writel(MDDI_CMD_PERIODIC_REV_ENCAP | 0, CMD);
619 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
620 mddi->reg_read = NULL;
621 mutex_unlock(&mddi->reg_read_lock);
622 return ri.result;
623}
624
625static struct mddi_info mddi_info[2];
626
627static int __init mddi_clk_setup(struct platform_device *pdev,
628 struct mddi_info *mddi,
629 unsigned long clk_rate)
630{
631 int ret;
632
633 /* set up the clocks */
634 mddi->clk = clk_get(&pdev->dev, "mddi_clk");
635 if (IS_ERR(mddi->clk)) {
636 printk(KERN_INFO "mddi: failed to get clock\n");
637 return PTR_ERR(mddi->clk);
638 }
639 ret = clk_enable(mddi->clk);
640 if (ret)
641 goto fail;
642 ret = clk_set_rate(mddi->clk, clk_rate);
643 if (ret)
644 goto fail;
645 return 0;
646
647fail:
648 clk_put(mddi->clk);
649 return ret;
650}
651
652static int __init mddi_rev_data_setup(struct mddi_info *mddi)
653{
654 void *dma;
655 dma_addr_t dma_addr;
656
657 /* set up dma buffer */
658 dma = dma_alloc_coherent(NULL, 0x1000, &dma_addr, GFP_KERNEL);
659 if (dma == 0)
660 return -ENOMEM;
661 mddi->rev_data = dma;
662 mddi->rev_data_curr = 0;
663 mddi->rev_addr = dma_addr;
664 mddi->reg_write_data = dma + MDDI_REV_BUFFER_SIZE;
665 mddi->reg_write_addr = dma_addr + MDDI_REV_BUFFER_SIZE;
666 mddi->reg_read_data = mddi->reg_write_data + 1;
667 mddi->reg_read_addr = mddi->reg_write_addr +
668 sizeof(*mddi->reg_write_data);
669 return 0;
670}
671
672static int __init mddi_probe(struct platform_device *pdev)
673{
674 struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
675 struct mddi_info *mddi = &mddi_info[pdev->id];
676 struct resource *resource;
677 int ret, i;
678
679 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
680 if (!resource) {
681 printk(KERN_ERR "mddi: no associated mem resource!\n");
682 return -ENOMEM;
683 }
684 mddi->base = ioremap(resource->start, resource->end - resource->start);
685 if (!mddi->base) {
686 printk(KERN_ERR "mddi: failed to remap base!\n");
687 ret = -EINVAL;
688 goto error_ioremap;
689 }
690 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
691 if (!resource) {
692 printk(KERN_ERR "mddi: no associated irq resource!\n");
693 ret = -EINVAL;
694 goto error_get_irq_resource;
695 }
696 mddi->irq = resource->start;
697 printk(KERN_INFO "mddi: init() base=0x%p irq=%d\n", mddi->base,
698 mddi->irq);
699 mddi->power_client = pdata->power_client;
700
701 mutex_init(&mddi->reg_write_lock);
702 mutex_init(&mddi->reg_read_lock);
703 spin_lock_init(&mddi->int_lock);
704 init_waitqueue_head(&mddi->int_wait);
705
706 ret = mddi_clk_setup(pdev, mddi, pdata->clk_rate);
707 if (ret) {
708 printk(KERN_ERR "mddi: failed to setup clock!\n");
709 goto error_clk_setup;
710 }
711
712 ret = mddi_rev_data_setup(mddi);
713 if (ret) {
714 printk(KERN_ERR "mddi: failed to setup rev data!\n");
715 goto error_rev_data;
716 }
717
718 mddi->int_enable = 0;
719 mddi_writel(mddi->int_enable, INTEN);
720 ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
721 &mddi->client_data);
722 if (ret) {
723 printk(KERN_ERR "mddi: failed to request enable irq!\n");
724 goto error_request_irq;
725 }
726
727 /* turn on the mddi client bridge chip */
728 if (mddi->power_client)
729 mddi->power_client(&mddi->client_data, 1);
730
731 /* initialize the mddi registers */
732 mddi_set_auto_hibernate(&mddi->client_data, 0);
733 mddi_writel(MDDI_CMD_RESET, CMD);
734 mddi_wait_interrupt(mddi, MDDI_INT_NO_CMD_PKTS_PEND);
735 mddi->version = mddi_init_registers(mddi);
736 if (mddi->version < 0x20) {
737 printk(KERN_ERR "mddi: unsupported version 0x%x\n",
738 mddi->version);
739 ret = -ENODEV;
740 goto error_mddi_version;
741 }
742
743 /* read the capabilities off the client */
744 if (!mddi_get_client_caps(mddi)) {
745 printk(KERN_INFO "mddi: no client found\n");
746 /* power down the panel */
747 mddi_writel(MDDI_CMD_POWERDOWN, CMD);
748 printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
749 msleep(100);
750 printk(KERN_INFO "mddi powerdown: stat %x\n", mddi_readl(STAT));
751 return 0;
752 }
753 mddi_set_auto_hibernate(&mddi->client_data, 1);
754
755 if (mddi->caps.Mfr_Name == 0 && mddi->caps.Product_Code == 0)
756 pdata->fixup(&mddi->caps.Mfr_Name, &mddi->caps.Product_Code);
757
758 mddi->client_pdev.id = 0;
759 for (i = 0; i < pdata->num_clients; i++) {
760 if (pdata->client_platform_data[i].product_id ==
761 (mddi->caps.Mfr_Name << 16 | mddi->caps.Product_Code)) {
762 mddi->client_data.private_client_data =
763 pdata->client_platform_data[i].client_data;
764 mddi->client_pdev.name =
765 pdata->client_platform_data[i].name;
766 mddi->client_pdev.id =
767 pdata->client_platform_data[i].id;
768 /* XXX: possibly set clock */
769 break;
770 }
771 }
772
773 if (i >= pdata->num_clients)
774 mddi->client_pdev.name = "mddi_c_dummy";
775 printk(KERN_INFO "mddi: registering panel %s\n",
776 mddi->client_pdev.name);
777
778 mddi->client_data.suspend = mddi_suspend;
779 mddi->client_data.resume = mddi_resume;
780 mddi->client_data.activate_link = mddi_activate_link;
781 mddi->client_data.remote_write = mddi_remote_write;
782 mddi->client_data.remote_read = mddi_remote_read;
783 mddi->client_data.auto_hibernate = mddi_set_auto_hibernate;
784 mddi->client_data.fb_resource = pdata->fb_resource;
785 if (pdev->id == 0)
786 mddi->client_data.interface_type = MSM_MDDI_PMDH_INTERFACE;
787 else if (pdev->id == 1)
788 mddi->client_data.interface_type = MSM_MDDI_EMDH_INTERFACE;
789 else {
790 printk(KERN_ERR "mddi: can not determine interface %d!\n",
791 pdev->id);
792 ret = -EINVAL;
793 goto error_mddi_interface;
794 }
795
796 mddi->client_pdev.dev.platform_data = &mddi->client_data;
797 printk(KERN_INFO "mddi: publish: %s\n", mddi->client_name);
798 platform_device_register(&mddi->client_pdev);
799 return 0;
800
801error_mddi_interface:
802error_mddi_version:
803 free_irq(mddi->irq, 0);
804error_request_irq:
805 dma_free_coherent(NULL, 0x1000, mddi->rev_data, mddi->rev_addr);
806error_rev_data:
807error_clk_setup:
808error_get_irq_resource:
809 iounmap(mddi->base);
810error_ioremap:
811
812 printk(KERN_INFO "mddi: mddi_init() failed (%d)\n", ret);
813 return ret;
814}
815
816
817static struct platform_driver mddi_driver = {
818 .probe = mddi_probe,
819 .driver = { .name = "msm_mddi" },
820};
821
822static int __init _mddi_init(void)
823{
824 return platform_driver_register(&mddi_driver);
825}
826
827module_init(_mddi_init);
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c
new file mode 100644
index 000000000000..ebbae87885b6
--- /dev/null
+++ b/drivers/video/msm/mddi_client_dummy.c
@@ -0,0 +1,97 @@
1/* drivers/video/msm_fb/mddi_client_dummy.c
2 *
3 * Support for "dummy" mddi client devices which require no
4 * special initialization code.
5 *
6 * Copyright (C) 2007 Google Incorporated
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21
22#include <mach/msm_fb.h>
23
24struct panel_info {
25 struct platform_device pdev;
26 struct msm_panel_data panel_data;
27};
28
29static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
30{
31 return 0;
32}
33
34static int mddi_dummy_resume(struct msm_panel_data *panel_data)
35{
36 return 0;
37}
38
39static int mddi_dummy_blank(struct msm_panel_data *panel_data)
40{
41 return 0;
42}
43
44static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
45{
46 return 0;
47}
48
49static int mddi_dummy_probe(struct platform_device *pdev)
50{
51 struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
52 struct panel_info *panel =
53 kzalloc(sizeof(struct panel_info), GFP_KERNEL);
54 int ret;
55 if (!panel)
56 return -ENOMEM;
57 platform_set_drvdata(pdev, panel);
58 panel->panel_data.suspend = mddi_dummy_suspend;
59 panel->panel_data.resume = mddi_dummy_resume;
60 panel->panel_data.blank = mddi_dummy_blank;
61 panel->panel_data.unblank = mddi_dummy_unblank;
62 panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
63 panel->pdev.name = "msm_panel";
64 panel->pdev.id = pdev->id;
65 platform_device_add_resources(&panel->pdev,
66 client_data->fb_resource, 1);
67 panel->panel_data.fb_data = client_data->private_client_data;
68 panel->pdev.dev.platform_data = &panel->panel_data;
69 ret = platform_device_register(&panel->pdev);
70 if (ret) {
71 kfree(panel);
72 return ret;
73 }
74 return 0;
75}
76
77static int mddi_dummy_remove(struct platform_device *pdev)
78{
79 struct panel_info *panel = platform_get_drvdata(pdev);
80 kfree(panel);
81 return 0;
82}
83
84static struct platform_driver mddi_client_dummy = {
85 .probe = mddi_dummy_probe,
86 .remove = mddi_dummy_remove,
87 .driver = { .name = "mddi_c_dummy" },
88};
89
90static int __init mddi_client_dummy_init(void)
91{
92 platform_driver_register(&mddi_client_dummy);
93 return 0;
94}
95
96module_init(mddi_client_dummy_init);
97
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
new file mode 100644
index 000000000000..c9e9349451cb
--- /dev/null
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -0,0 +1,256 @@
1/* drivers/video/msm_fb/mddi_client_nt35399.c
2 *
3 * Support for Novatek NT35399 MDDI client of Sapphire
4 *
5 * Copyright (C) 2008 HTC Incorporated
6 * Author: Solomon Chiu (solomon_chiu@htc.com)
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21#include <linux/interrupt.h>
22#include <linux/sched.h>
23#include <linux/gpio.h>
24#include <mach/msm_fb.h>
25
26static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
27
28struct panel_info {
29 struct msm_mddi_client_data *client_data;
30 struct platform_device pdev;
31 struct msm_panel_data panel_data;
32 struct msmfb_callback *fb_callback;
33 struct work_struct panel_work;
34 struct workqueue_struct *fb_wq;
35 int nt35399_got_int;
36};
37
38static void
39nt35399_request_vsync(struct msm_panel_data *panel_data,
40 struct msmfb_callback *callback)
41{
42 struct panel_info *panel = container_of(panel_data, struct panel_info,
43 panel_data);
44 struct msm_mddi_client_data *client_data = panel->client_data;
45
46 panel->fb_callback = callback;
47 if (panel->nt35399_got_int) {
48 panel->nt35399_got_int = 0;
49 client_data->activate_link(client_data); /* clears interrupt */
50 }
51}
52
53static void nt35399_wait_vsync(struct msm_panel_data *panel_data)
54{
55 struct panel_info *panel = container_of(panel_data, struct panel_info,
56 panel_data);
57 struct msm_mddi_client_data *client_data = panel->client_data;
58
59 if (panel->nt35399_got_int) {
60 panel->nt35399_got_int = 0;
61 client_data->activate_link(client_data); /* clears interrupt */
62 }
63
64 if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int,
65 HZ/2) == 0)
66 printk(KERN_ERR "timeout waiting for VSYNC\n");
67
68 panel->nt35399_got_int = 0;
69 /* interrupt clears when screen dma starts */
70}
71
72static int nt35399_suspend(struct msm_panel_data *panel_data)
73{
74 struct panel_info *panel = container_of(panel_data, struct panel_info,
75 panel_data);
76 struct msm_mddi_client_data *client_data = panel->client_data;
77
78 struct msm_mddi_bridge_platform_data *bridge_data =
79 client_data->private_client_data;
80 int ret;
81
82 ret = bridge_data->uninit(bridge_data, client_data);
83 if (ret) {
84 printk(KERN_INFO "mddi nt35399 client: non zero return from "
85 "uninit\n");
86 return ret;
87 }
88 client_data->suspend(client_data);
89 return 0;
90}
91
92static int nt35399_resume(struct msm_panel_data *panel_data)
93{
94 struct panel_info *panel = container_of(panel_data, struct panel_info,
95 panel_data);
96 struct msm_mddi_client_data *client_data = panel->client_data;
97
98 struct msm_mddi_bridge_platform_data *bridge_data =
99 client_data->private_client_data;
100 int ret;
101
102 client_data->resume(client_data);
103 ret = bridge_data->init(bridge_data, client_data);
104 if (ret)
105 return ret;
106 return 0;
107}
108
109static int nt35399_blank(struct msm_panel_data *panel_data)
110{
111 struct panel_info *panel = container_of(panel_data, struct panel_info,
112 panel_data);
113 struct msm_mddi_client_data *client_data = panel->client_data;
114 struct msm_mddi_bridge_platform_data *bridge_data =
115 client_data->private_client_data;
116
117 return bridge_data->blank(bridge_data, client_data);
118}
119
120static int nt35399_unblank(struct msm_panel_data *panel_data)
121{
122 struct panel_info *panel = container_of(panel_data, struct panel_info,
123 panel_data);
124 struct msm_mddi_client_data *client_data = panel->client_data;
125 struct msm_mddi_bridge_platform_data *bridge_data =
126 client_data->private_client_data;
127
128 return bridge_data->unblank(bridge_data, client_data);
129}
130
131irqreturn_t nt35399_vsync_interrupt(int irq, void *data)
132{
133 struct panel_info *panel = data;
134
135 panel->nt35399_got_int = 1;
136
137 if (panel->fb_callback) {
138 panel->fb_callback->func(panel->fb_callback);
139 panel->fb_callback = NULL;
140 }
141
142 wake_up(&nt35399_vsync_wait);
143
144 return IRQ_HANDLED;
145}
146
147static int setup_vsync(struct panel_info *panel, int init)
148{
149 int ret;
150 int gpio = 97;
151 unsigned int irq;
152
153 if (!init) {
154 ret = 0;
155 goto uninit;
156 }
157 ret = gpio_request(gpio, "vsync");
158 if (ret)
159 goto err_request_gpio_failed;
160
161 ret = gpio_direction_input(gpio);
162 if (ret)
163 goto err_gpio_direction_input_failed;
164
165 ret = irq = gpio_to_irq(gpio);
166 if (ret < 0)
167 goto err_get_irq_num_failed;
168
169 ret = request_irq(irq, nt35399_vsync_interrupt, IRQF_TRIGGER_RISING,
170 "vsync", panel);
171 if (ret)
172 goto err_request_irq_failed;
173
174 printk(KERN_INFO "vsync on gpio %d now %d\n",
175 gpio, gpio_get_value(gpio));
176 return 0;
177
178uninit:
179 free_irq(gpio_to_irq(gpio), panel->client_data);
180err_request_irq_failed:
181err_get_irq_num_failed:
182err_gpio_direction_input_failed:
183 gpio_free(gpio);
184err_request_gpio_failed:
185 return ret;
186}
187
188static int mddi_nt35399_probe(struct platform_device *pdev)
189{
190 struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
191 struct msm_mddi_bridge_platform_data *bridge_data =
192 client_data->private_client_data;
193
194 int ret;
195
196 struct panel_info *panel = kzalloc(sizeof(struct panel_info),
197 GFP_KERNEL);
198
199 printk(KERN_DEBUG "%s: enter.\n", __func__);
200
201 if (!panel)
202 return -ENOMEM;
203 platform_set_drvdata(pdev, panel);
204
205 ret = setup_vsync(panel, 1);
206 if (ret) {
207 dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n");
208 return ret;
209 }
210
211 panel->client_data = client_data;
212 panel->panel_data.suspend = nt35399_suspend;
213 panel->panel_data.resume = nt35399_resume;
214 panel->panel_data.wait_vsync = nt35399_wait_vsync;
215 panel->panel_data.request_vsync = nt35399_request_vsync;
216 panel->panel_data.blank = nt35399_blank;
217 panel->panel_data.unblank = nt35399_unblank;
218 panel->panel_data.fb_data = &bridge_data->fb_data;
219 panel->panel_data.caps = 0;
220
221 panel->pdev.name = "msm_panel";
222 panel->pdev.id = pdev->id;
223 panel->pdev.resource = client_data->fb_resource;
224 panel->pdev.num_resources = 1;
225 panel->pdev.dev.platform_data = &panel->panel_data;
226
227 if (bridge_data->init)
228 bridge_data->init(bridge_data, client_data);
229
230 platform_device_register(&panel->pdev);
231
232 return 0;
233}
234
235static int mddi_nt35399_remove(struct platform_device *pdev)
236{
237 struct panel_info *panel = platform_get_drvdata(pdev);
238
239 setup_vsync(panel, 0);
240 kfree(panel);
241 return 0;
242}
243
244static struct platform_driver mddi_client_0bda_8a47 = {
245 .probe = mddi_nt35399_probe,
246 .remove = mddi_nt35399_remove,
247 .driver = { .name = "mddi_c_0bda_8a47" },
248};
249
250static int __init mddi_client_nt35399_init(void)
251{
252 return platform_driver_register(&mddi_client_0bda_8a47);
253}
254
255module_init(mddi_client_nt35399_init);
256
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
new file mode 100644
index 000000000000..71048e78f7f0
--- /dev/null
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -0,0 +1,284 @@
1/* drivers/video/msm_fb/mddi_client_toshiba.c
2 *
3 * Support for Toshiba TC358720XBG mddi client devices which require no
4 * special initialization code.
5 *
6 * Copyright (C) 2007 Google Incorporated
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21#include <linux/interrupt.h>
22#include <linux/gpio.h>
23#include <linux/sched.h>
24#include <mach/msm_fb.h>
25
26
27#define LCD_CONTROL_BLOCK_BASE 0x110000
28#define CMN (LCD_CONTROL_BLOCK_BASE|0x10)
29#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
30#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
31#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
32#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0)
33#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
34#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
35#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58)
36#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
37
38#define BASE5 0x150000
39#define BASE6 0x160000
40#define BASE7 0x170000
41
42#define GPIOIEV (BASE5 + 0x10)
43#define GPIOIE (BASE5 + 0x14)
44#define GPIORIS (BASE5 + 0x18)
45#define GPIOMIS (BASE5 + 0x1C)
46#define GPIOIC (BASE5 + 0x20)
47
48#define INTMASK (BASE6 + 0x0C)
49#define INTMASK_VWAKEOUT (1U << 0)
50#define INTMASK_VWAKEOUT_ACTIVE_LOW (1U << 8)
51#define GPIOSEL (BASE7 + 0x00)
52#define GPIOSEL_VWAKEINT (1U << 0)
53
54static DECLARE_WAIT_QUEUE_HEAD(toshiba_vsync_wait);
55
56struct panel_info {
57 struct msm_mddi_client_data *client_data;
58 struct platform_device pdev;
59 struct msm_panel_data panel_data;
60 struct msmfb_callback *toshiba_callback;
61 int toshiba_got_int;
62};
63
64
65static void toshiba_request_vsync(struct msm_panel_data *panel_data,
66 struct msmfb_callback *callback)
67{
68 struct panel_info *panel = container_of(panel_data, struct panel_info,
69 panel_data);
70 struct msm_mddi_client_data *client_data = panel->client_data;
71
72 panel->toshiba_callback = callback;
73 if (panel->toshiba_got_int) {
74 panel->toshiba_got_int = 0;
75 client_data->activate_link(client_data);
76 }
77}
78
79static void toshiba_clear_vsync(struct msm_panel_data *panel_data)
80{
81 struct panel_info *panel = container_of(panel_data, struct panel_info,
82 panel_data);
83 struct msm_mddi_client_data *client_data = panel->client_data;
84
85 client_data->activate_link(client_data);
86}
87
88static void toshiba_wait_vsync(struct msm_panel_data *panel_data)
89{
90 struct panel_info *panel = container_of(panel_data, struct panel_info,
91 panel_data);
92 struct msm_mddi_client_data *client_data = panel->client_data;
93
94 if (panel->toshiba_got_int) {
95 panel->toshiba_got_int = 0;
96 client_data->activate_link(client_data); /* clears interrupt */
97 }
98 if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int,
99 HZ/2) == 0)
100 printk(KERN_ERR "timeout waiting for VSYNC\n");
101 panel->toshiba_got_int = 0;
102 /* interrupt clears when screen dma starts */
103}
104
105static int toshiba_suspend(struct msm_panel_data *panel_data)
106{
107 struct panel_info *panel = container_of(panel_data, struct panel_info,
108 panel_data);
109 struct msm_mddi_client_data *client_data = panel->client_data;
110
111 struct msm_mddi_bridge_platform_data *bridge_data =
112 client_data->private_client_data;
113 int ret;
114
115 ret = bridge_data->uninit(bridge_data, client_data);
116 if (ret) {
117 printk(KERN_INFO "mddi toshiba client: non zero return from "
118 "uninit\n");
119 return ret;
120 }
121 client_data->suspend(client_data);
122 return 0;
123}
124
125static int toshiba_resume(struct msm_panel_data *panel_data)
126{
127 struct panel_info *panel = container_of(panel_data, struct panel_info,
128 panel_data);
129 struct msm_mddi_client_data *client_data = panel->client_data;
130
131 struct msm_mddi_bridge_platform_data *bridge_data =
132 client_data->private_client_data;
133 int ret;
134
135 client_data->resume(client_data);
136 ret = bridge_data->init(bridge_data, client_data);
137 if (ret)
138 return ret;
139 return 0;
140}
141
142static int toshiba_blank(struct msm_panel_data *panel_data)
143{
144 struct panel_info *panel = container_of(panel_data, struct panel_info,
145 panel_data);
146 struct msm_mddi_client_data *client_data = panel->client_data;
147 struct msm_mddi_bridge_platform_data *bridge_data =
148 client_data->private_client_data;
149
150 return bridge_data->blank(bridge_data, client_data);
151}
152
153static int toshiba_unblank(struct msm_panel_data *panel_data)
154{
155 struct panel_info *panel = container_of(panel_data, struct panel_info,
156 panel_data);
157 struct msm_mddi_client_data *client_data = panel->client_data;
158 struct msm_mddi_bridge_platform_data *bridge_data =
159 client_data->private_client_data;
160
161 return bridge_data->unblank(bridge_data, client_data);
162}
163
164irqreturn_t toshiba_vsync_interrupt(int irq, void *data)
165{
166 struct panel_info *panel = data;
167
168 panel->toshiba_got_int = 1;
169 if (panel->toshiba_callback) {
170 panel->toshiba_callback->func(panel->toshiba_callback);
171 panel->toshiba_callback = 0;
172 }
173 wake_up(&toshiba_vsync_wait);
174 return IRQ_HANDLED;
175}
176
177static int setup_vsync(struct panel_info *panel,
178 int init)
179{
180 int ret;
181 int gpio = 97;
182 unsigned int irq;
183
184 if (!init) {
185 ret = 0;
186 goto uninit;
187 }
188 ret = gpio_request(gpio, "vsync");
189 if (ret)
190 goto err_request_gpio_failed;
191
192 ret = gpio_direction_input(gpio);
193 if (ret)
194 goto err_gpio_direction_input_failed;
195
196 ret = irq = gpio_to_irq(gpio);
197 if (ret < 0)
198 goto err_get_irq_num_failed;
199
200 ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING,
201 "vsync", panel);
202 if (ret)
203 goto err_request_irq_failed;
204 printk(KERN_INFO "vsync on gpio %d now %d\n",
205 gpio, gpio_get_value(gpio));
206 return 0;
207
208uninit:
209 free_irq(gpio_to_irq(gpio), panel);
210err_request_irq_failed:
211err_get_irq_num_failed:
212err_gpio_direction_input_failed:
213 gpio_free(gpio);
214err_request_gpio_failed:
215 return ret;
216}
217
218static int mddi_toshiba_probe(struct platform_device *pdev)
219{
220 int ret;
221 struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
222 struct msm_mddi_bridge_platform_data *bridge_data =
223 client_data->private_client_data;
224 struct panel_info *panel =
225 kzalloc(sizeof(struct panel_info), GFP_KERNEL);
226 if (!panel)
227 return -ENOMEM;
228 platform_set_drvdata(pdev, panel);
229
230 /* mddi_remote_write(mddi, 0, WAKEUP); */
231 client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL);
232 client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK);
233
234 ret = setup_vsync(panel, 1);
235 if (ret) {
236 dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
237 return ret;
238 }
239
240 panel->client_data = client_data;
241 panel->panel_data.suspend = toshiba_suspend;
242 panel->panel_data.resume = toshiba_resume;
243 panel->panel_data.wait_vsync = toshiba_wait_vsync;
244 panel->panel_data.request_vsync = toshiba_request_vsync;
245 panel->panel_data.clear_vsync = toshiba_clear_vsync;
246 panel->panel_data.blank = toshiba_blank;
247 panel->panel_data.unblank = toshiba_unblank;
248 panel->panel_data.fb_data = &bridge_data->fb_data;
249 panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
250
251 panel->pdev.name = "msm_panel";
252 panel->pdev.id = pdev->id;
253 panel->pdev.resource = client_data->fb_resource;
254 panel->pdev.num_resources = 1;
255 panel->pdev.dev.platform_data = &panel->panel_data;
256 bridge_data->init(bridge_data, client_data);
257 platform_device_register(&panel->pdev);
258
259 return 0;
260}
261
262static int mddi_toshiba_remove(struct platform_device *pdev)
263{
264 struct panel_info *panel = platform_get_drvdata(pdev);
265
266 setup_vsync(panel, 0);
267 kfree(panel);
268 return 0;
269}
270
271static struct platform_driver mddi_client_d263_0000 = {
272 .probe = mddi_toshiba_probe,
273 .remove = mddi_toshiba_remove,
274 .driver = { .name = "mddi_c_d263_0000" },
275};
276
277static int __init mddi_client_toshiba_init(void)
278{
279 platform_driver_register(&mddi_client_d263_0000);
280 return 0;
281}
282
283module_init(mddi_client_toshiba_init);
284
diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/msm/mddi_hw.h
new file mode 100644
index 000000000000..45cc01fc1e7f
--- /dev/null
+++ b/drivers/video/msm/mddi_hw.h
@@ -0,0 +1,305 @@
1/* drivers/video/msm_fb/mddi_hw.h
2 *
3 * MSM MDDI Hardware Registers and Structures
4 *
5 * Copyright (C) 2007 QUALCOMM Incorporated
6 * Copyright (C) 2007 Google Incorporated
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#ifndef _MDDI_HW_H_
19#define _MDDI_HW_H_
20
21#include <linux/types.h>
22
23#define MDDI_CMD 0x0000
24#define MDDI_VERSION 0x0004
25#define MDDI_PRI_PTR 0x0008
26#define MDDI_SEC_PTR 0x000c
27#define MDDI_BPS 0x0010
28#define MDDI_SPM 0x0014
29#define MDDI_INT 0x0018
30#define MDDI_INTEN 0x001c
31#define MDDI_REV_PTR 0x0020
32#define MDDI_REV_SIZE 0x0024
33#define MDDI_STAT 0x0028
34#define MDDI_REV_RATE_DIV 0x002c
35#define MDDI_REV_CRC_ERR 0x0030
36#define MDDI_TA1_LEN 0x0034
37#define MDDI_TA2_LEN 0x0038
38#define MDDI_TEST_BUS 0x003c
39#define MDDI_TEST 0x0040
40#define MDDI_REV_PKT_CNT 0x0044
41#define MDDI_DRIVE_HI 0x0048
42#define MDDI_DRIVE_LO 0x004c
43#define MDDI_DISP_WAKE 0x0050
44#define MDDI_REV_ENCAP_SZ 0x0054
45#define MDDI_RTD_VAL 0x0058
46#define MDDI_PAD_CTL 0x0068
47#define MDDI_DRIVER_START_CNT 0x006c
48#define MDDI_NEXT_PRI_PTR 0x0070
49#define MDDI_NEXT_SEC_PTR 0x0074
50#define MDDI_MISR_CTL 0x0078
51#define MDDI_MISR_DATA 0x007c
52#define MDDI_SF_CNT 0x0080
53#define MDDI_MF_CNT 0x0084
54#define MDDI_CURR_REV_PTR 0x0088
55#define MDDI_CORE_VER 0x008c
56
57#define MDDI_INT_PRI_PTR_READ 0x0001
58#define MDDI_INT_SEC_PTR_READ 0x0002
59#define MDDI_INT_REV_DATA_AVAIL 0x0004
60#define MDDI_INT_DISP_REQ 0x0008
61#define MDDI_INT_PRI_UNDERFLOW 0x0010
62#define MDDI_INT_SEC_UNDERFLOW 0x0020
63#define MDDI_INT_REV_OVERFLOW 0x0040
64#define MDDI_INT_CRC_ERROR 0x0080
65#define MDDI_INT_MDDI_IN 0x0100
66#define MDDI_INT_PRI_OVERWRITE 0x0200
67#define MDDI_INT_SEC_OVERWRITE 0x0400
68#define MDDI_INT_REV_OVERWRITE 0x0800
69#define MDDI_INT_DMA_FAILURE 0x1000
70#define MDDI_INT_LINK_ACTIVE 0x2000
71#define MDDI_INT_IN_HIBERNATION 0x4000
72#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
73#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
74#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000
75#define MDDI_INT_RTD_FAILURE 0x40000
76#define MDDI_INT_REV_PKT_RECEIVED 0x80000
77#define MDDI_INT_REV_PKTS_AVAIL 0x100000
78
79#define MDDI_INT_NEED_CLEAR ( \
80 MDDI_INT_REV_DATA_AVAIL | \
81 MDDI_INT_PRI_UNDERFLOW | \
82 MDDI_INT_SEC_UNDERFLOW | \
83 MDDI_INT_REV_OVERFLOW | \
84 MDDI_INT_CRC_ERROR | \
85 MDDI_INT_REV_PKT_RECEIVED)
86
87
88#define MDDI_STAT_LINK_ACTIVE 0x0001
89#define MDDI_STAT_NEW_REV_PTR 0x0002
90#define MDDI_STAT_NEW_PRI_PTR 0x0004
91#define MDDI_STAT_NEW_SEC_PTR 0x0008
92#define MDDI_STAT_IN_HIBERNATION 0x0010
93#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
94#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
95#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
96#define MDDI_STAT_PENDING_REV_ENCAP 0x0100
97#define MDDI_STAT_PENDING_POWERDOWN 0x0200
98#define MDDI_STAT_RTD_MEAS_FAIL 0x0800
99#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000
100
101
102#define MDDI_CMD_POWERDOWN 0x0100
103#define MDDI_CMD_POWERUP 0x0200
104#define MDDI_CMD_HIBERNATE 0x0300
105#define MDDI_CMD_RESET 0x0400
106#define MDDI_CMD_DISP_IGNORE 0x0501
107#define MDDI_CMD_DISP_LISTEN 0x0500
108#define MDDI_CMD_SEND_REV_ENCAP 0x0600
109#define MDDI_CMD_GET_CLIENT_CAP 0x0601
110#define MDDI_CMD_GET_CLIENT_STATUS 0x0602
111#define MDDI_CMD_SEND_RTD 0x0700
112#define MDDI_CMD_LINK_ACTIVE 0x0900
113#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
114#define MDDI_CMD_FORCE_NEW_REV_PTR 0x0C00
115
116
117
118#define MDDI_VIDEO_REV_PKT_SIZE 0x40
119#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
120#define MDDI_MAX_REV_PKT_SIZE 0x60
121
122/* #define MDDI_REV_BUFFER_SIZE 128 */
123#define MDDI_REV_BUFFER_SIZE (MDDI_MAX_REV_PKT_SIZE * 4)
124
125/* MDP sends 256 pixel packets, so lower value hibernates more without
126 * significantly increasing latency of waiting for next subframe */
127#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
128#define MDDI_HOST_TA2_LEN 0x000c
129#define MDDI_HOST_REV_RATE_DIV 0x0002
130
131
132struct __attribute__((packed)) mddi_rev_packet {
133 uint16_t length;
134 uint16_t type;
135 uint16_t client_id;
136};
137
138struct __attribute__((packed)) mddi_client_status {
139 uint16_t length;
140 uint16_t type;
141 uint16_t client_id;
142 uint16_t reverse_link_request; /* bytes needed in rev encap message */
143 uint8_t crc_error_count;
144 uint8_t capability_change;
145 uint16_t graphics_busy_flags;
146 uint16_t crc16;
147};
148
149struct __attribute__((packed)) mddi_client_caps {
150 uint16_t length; /* length, exclusive of this field */
151 uint16_t type; /* 66 */
152 uint16_t client_id;
153
154 uint16_t Protocol_Version;
155 uint16_t Minimum_Protocol_Version;
156 uint16_t Data_Rate_Capability;
157 uint8_t Interface_Type_Capability;
158 uint8_t Number_of_Alt_Displays;
159 uint16_t PostCal_Data_Rate;
160 uint16_t Bitmap_Width;
161 uint16_t Bitmap_Height;
162 uint16_t Display_Window_Width;
163 uint16_t Display_Window_Height;
164 uint32_t Color_Map_Size;
165 uint16_t Color_Map_RGB_Width;
166 uint16_t RGB_Capability;
167 uint8_t Monochrome_Capability;
168 uint8_t Reserved_1;
169 uint16_t Y_Cb_Cr_Capability;
170 uint16_t Bayer_Capability;
171 uint16_t Alpha_Cursor_Image_Planes;
172 uint32_t Client_Feature_Capability_Indicators;
173 uint8_t Maximum_Video_Frame_Rate_Capability;
174 uint8_t Minimum_Video_Frame_Rate_Capability;
175 uint16_t Minimum_Sub_frame_Rate;
176 uint16_t Audio_Buffer_Depth;
177 uint16_t Audio_Channel_Capability;
178 uint16_t Audio_Sample_Rate_Capability;
179 uint8_t Audio_Sample_Resolution;
180 uint8_t Mic_Audio_Sample_Resolution;
181 uint16_t Mic_Sample_Rate_Capability;
182 uint8_t Keyboard_Data_Format;
183 uint8_t pointing_device_data_format;
184 uint16_t content_protection_type;
185 uint16_t Mfr_Name;
186 uint16_t Product_Code;
187 uint16_t Reserved_3;
188 uint32_t Serial_Number;
189 uint8_t Week_of_Manufacture;
190 uint8_t Year_of_Manufacture;
191
192 uint16_t crc16;
193} mddi_client_capability_type;
194
195
196struct __attribute__((packed)) mddi_video_stream {
197 uint16_t length;
198 uint16_t type; /* 16 */
199 uint16_t client_id; /* 0 */
200
201 uint16_t video_data_format_descriptor;
202/* format of each pixel in the Pixel Data in the present stream in the
203 * present packet.
204 * If bits [15:13] = 000 monochrome
205 * If bits [15:13] = 001 color pixels (palette).
206 * If bits [15:13] = 010 color pixels in raw RGB
207 * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
208 * If bits [15:13] = 100 Bayer pixels
209 */
210
211 uint16_t pixel_data_attributes;
212/* interpreted as follows:
213 * Bits [1:0] = 11 pixel data is displayed to both eyes
214 * Bits [1:0] = 10 pixel data is routed to the left eye only.
215 * Bits [1:0] = 01 pixel data is routed to the right eye only.
216 * Bits [1:0] = 00 pixel data is routed to the alternate display.
217 * Bit 2 is 0 Pixel Data is in the standard progressive format.
218 * Bit 2 is 1 Pixel Data is in interlace format.
219 * Bit 3 is 0 Pixel Data is in the standard progressive format.
220 * Bit 3 is 1 Pixel Data is in alternate pixel format.
221 * Bit 4 is 0 Pixel Data is to or from the display frame buffer.
222 * Bit 4 is 1 Pixel Data is to or from the camera.
223 * Bit 5 is 0 pixel data contains the next consecutive row of pixels.
224 * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
225 * X Start, and Y Start parameters are not defined and
226 * shall be ignored by the client.
227 * Bits [7:6] = 01 Pixel data is written to the offline image buffer.
228 * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display.
229 * Bits [7:6] = 11 Pixel data is written to all image buffers.
230 * Bits [7:6] = 10 Invalid. Reserved for future use.
231 * Bits 8 through 11 alternate display number.
232 * Bits 12 through 14 are reserved for future use and shall be set to zero.
233 * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
234 */
235
236 uint16_t x_left_edge;
237 uint16_t y_top_edge;
238 /* X,Y coordinate of the top left edge of the screen window */
239
240 uint16_t x_right_edge;
241 uint16_t y_bottom_edge;
242 /* X,Y coordinate of the bottom right edge of the window being
243 * updated. */
244
245 uint16_t x_start;
246 uint16_t y_start;
247 /* (X Start, Y Start) is the first pixel in the Pixel Data field
248 * below. */
249
250 uint16_t pixel_count;
251 /* number of pixels in the Pixel Data field below. */
252
253 uint16_t parameter_CRC;
254 /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
255
256 uint16_t reserved;
257 /* 16-bit variable to make structure align on 4 byte boundary */
258};
259
260#define TYPE_VIDEO_STREAM 16
261#define TYPE_CLIENT_CAPS 66
262#define TYPE_REGISTER_ACCESS 146
263#define TYPE_CLIENT_STATUS 70
264
265struct __attribute__((packed)) mddi_register_access {
266 uint16_t length;
267 uint16_t type; /* 146 */
268 uint16_t client_id;
269
270 uint16_t read_write_info;
271 /* Bits 13:0 a 14-bit unsigned integer that specifies the number of
272 * 32-bit Register Data List items to be transferred in the
273 * Register Data List field.
274 * Bits[15:14] = 00 Write to register(s);
275 * Bits[15:14] = 10 Read from register(s);
276 * Bits[15:14] = 11 Response to a Read.
277 * Bits[15:14] = 01 this value is reserved for future use. */
278#define MDDI_WRITE (0 << 14)
279#define MDDI_READ (2 << 14)
280#define MDDI_READ_RESP (3 << 14)
281
282 uint32_t register_address;
283 /* the register address that is to be written to or read from. */
284
285 uint16_t crc16;
286
287 uint32_t register_data_list;
288 /* list of 4-byte register data values for/from client registers */
289};
290
291struct __attribute__((packed)) mddi_llentry {
292 uint16_t flags;
293 uint16_t header_count;
294 uint16_t data_count;
295 dma_addr_t data; /* 32 bit */
296 struct mddi_llentry *next;
297 uint16_t reserved;
298 union {
299 struct mddi_video_stream v;
300 struct mddi_register_access r;
301 uint32_t _[12];
302 } u;
303};
304
305#endif
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
new file mode 100644
index 000000000000..6c519e2fa2b7
--- /dev/null
+++ b/drivers/video/msm/mdp.c
@@ -0,0 +1,520 @@
1/* drivers/video/msm_fb/mdp.c
2 *
3 * MSM MDP Interface (used by framebuffer core)
4 *
5 * Copyright (C) 2007 QUALCOMM Incorporated
6 * Copyright (C) 2007 Google Incorporated
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/fb.h>
20#include <linux/msm_mdp.h>
21#include <linux/interrupt.h>
22#include <linux/wait.h>
23#include <linux/clk.h>
24#include <linux/file.h>
25#include <linux/major.h>
26
27#include <mach/msm_iomap.h>
28#include <mach/msm_fb.h>
29#include <linux/platform_device.h>
30
31#include "mdp_hw.h"
32
33struct class *mdp_class;
34
35#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
36
37static uint16_t mdp_default_ccs[] = {
38 0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
39 0x010, 0x080, 0x080
40};
41
42static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
43static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
44static struct msmfb_callback *dma_callback;
45static struct clk *clk;
46static unsigned int mdp_irq_mask;
47static DEFINE_SPINLOCK(mdp_lock);
48DEFINE_MUTEX(mdp_mutex);
49
50static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
51{
52 unsigned long irq_flags;
53 int ret = 0;
54
55 BUG_ON(!mask);
56
57 spin_lock_irqsave(&mdp_lock, irq_flags);
58 /* if the mask bits are already set return an error, this interrupt
59 * is already enabled */
60 if (mdp_irq_mask & mask) {
61 printk(KERN_ERR "mdp irq already on already on %x %x\n",
62 mdp_irq_mask, mask);
63 ret = -1;
64 }
65 /* if the mdp irq is not already enabled enable it */
66 if (!mdp_irq_mask) {
67 if (clk)
68 clk_enable(clk);
69 enable_irq(mdp->irq);
70 }
71
72 /* update the irq mask to reflect the fact that the interrupt is
73 * enabled */
74 mdp_irq_mask |= mask;
75 spin_unlock_irqrestore(&mdp_lock, irq_flags);
76 return ret;
77}
78
79static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
80{
81 /* this interrupt is already disabled! */
82 if (!(mdp_irq_mask & mask)) {
83 printk(KERN_ERR "mdp irq already off %x %x\n",
84 mdp_irq_mask, mask);
85 return -1;
86 }
87 /* update the irq mask to reflect the fact that the interrupt is
88 * disabled */
89 mdp_irq_mask &= ~(mask);
90 /* if no one is waiting on the interrupt, disable it */
91 if (!mdp_irq_mask) {
92 disable_irq(mdp->irq);
93 if (clk)
94 clk_disable(clk);
95 }
96 return 0;
97}
98
99static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
100{
101 unsigned long irq_flags;
102 int ret;
103
104 spin_lock_irqsave(&mdp_lock, irq_flags);
105 ret = locked_disable_mdp_irq(mdp, mask);
106 spin_unlock_irqrestore(&mdp_lock, irq_flags);
107 return ret;
108}
109
110static irqreturn_t mdp_isr(int irq, void *data)
111{
112 uint32_t status;
113 unsigned long irq_flags;
114 struct mdp_info *mdp = data;
115
116 spin_lock_irqsave(&mdp_lock, irq_flags);
117
118 status = mdp_readl(mdp, MDP_INTR_STATUS);
119 mdp_writel(mdp, status, MDP_INTR_CLEAR);
120
121 status &= mdp_irq_mask;
122 if (status & DL0_DMA2_TERM_DONE) {
123 if (dma_callback) {
124 dma_callback->func(dma_callback);
125 dma_callback = NULL;
126 }
127 wake_up(&mdp_dma2_waitqueue);
128 }
129
130 if (status & DL0_ROI_DONE)
131 wake_up(&mdp_ppp_waitqueue);
132
133 if (status)
134 locked_disable_mdp_irq(mdp, status);
135
136 spin_unlock_irqrestore(&mdp_lock, irq_flags);
137 return IRQ_HANDLED;
138}
139
140static uint32_t mdp_check_mask(uint32_t mask)
141{
142 uint32_t ret;
143 unsigned long irq_flags;
144
145 spin_lock_irqsave(&mdp_lock, irq_flags);
146 ret = mdp_irq_mask & mask;
147 spin_unlock_irqrestore(&mdp_lock, irq_flags);
148 return ret;
149}
150
151static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
152{
153 int ret = 0;
154 unsigned long irq_flags;
155
156 wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
157
158 spin_lock_irqsave(&mdp_lock, irq_flags);
159 if (mdp_irq_mask & mask) {
160 locked_disable_mdp_irq(mdp, mask);
161 printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
162 mask);
163 ret = -ETIMEDOUT;
164 }
165 spin_unlock_irqrestore(&mdp_lock, irq_flags);
166
167 return ret;
168}
169
170void mdp_dma_wait(struct mdp_device *mdp_dev)
171{
172#define MDP_MAX_TIMEOUTS 20
173 static int timeout_count;
174 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
175
176 if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
177 timeout_count++;
178 else
179 timeout_count = 0;
180
181 if (timeout_count > MDP_MAX_TIMEOUTS) {
182 printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
183 MDP_MAX_TIMEOUTS);
184 BUG();
185 }
186}
187
188static int mdp_ppp_wait(struct mdp_info *mdp)
189{
190 return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
191}
192
193void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
194 uint32_t width, uint32_t height, uint32_t x, uint32_t y,
195 struct msmfb_callback *callback)
196{
197 uint32_t dma2_cfg;
198 uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
199
200 if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
201 printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
202 return;
203 }
204
205 dma_callback = callback;
206
207 dma2_cfg = DMA_PACK_TIGHT |
208 DMA_PACK_ALIGN_LSB |
209 DMA_PACK_PATTERN_RGB |
210 DMA_OUT_SEL_AHB |
211 DMA_IBUF_NONCONTIGUOUS;
212
213 dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
214
215 dma2_cfg |= DMA_OUT_SEL_MDDI;
216
217 dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
218
219 dma2_cfg |= DMA_DITHER_EN;
220
221 /* setup size, address, and stride */
222 mdp_writel(mdp, (height << 16) | (width),
223 MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
224 mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
225 mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
226
227 /* 666 18BPP */
228 dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
229
230 /* set y & x offset and MDDI transaction parameters */
231 mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
232 mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
233 mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
234 MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
235
236 mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
237
238 /* start DMA2 */
239 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
240}
241
242void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
243 uint32_t width, uint32_t height, uint32_t x, uint32_t y,
244 struct msmfb_callback *callback, int interface)
245{
246 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
247
248 if (interface == MSM_MDDI_PMDH_INTERFACE) {
249 mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
250 callback);
251 }
252}
253
254int get_img(struct mdp_img *img, struct fb_info *info,
255 unsigned long *start, unsigned long *len,
256 struct file **filep)
257{
258 int put_needed, ret = 0;
259 struct file *file;
260 unsigned long vstart;
261
262 file = fget_light(img->memory_id, &put_needed);
263 if (file == NULL)
264 return -1;
265
266 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
267 *start = info->fix.smem_start;
268 *len = info->fix.smem_len;
269 } else
270 ret = -1;
271 fput_light(file, put_needed);
272
273 return ret;
274}
275
276void put_img(struct file *src_file, struct file *dst_file)
277{
278}
279
280int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
281 struct mdp_blit_req *req)
282{
283 int ret;
284 unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
285 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
286 struct file *src_file = 0, *dst_file = 0;
287
288 /* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
289 if (unlikely(req->src_rect.h == 0 ||
290 req->src_rect.w == 0)) {
291 printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
292 return -EINVAL;
293 }
294 if (unlikely(req->dst_rect.h == 0 ||
295 req->dst_rect.w == 0))
296 return -EINVAL;
297
298 /* do this first so that if this fails, the caller can always
299 * safely call put_img */
300 if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
301 printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
302 "memory\n");
303 return -EINVAL;
304 }
305
306 if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
307 printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
308 "memory\n");
309 return -EINVAL;
310 }
311 mutex_lock(&mdp_mutex);
312
313 /* transp_masking unimplemented */
314 req->transp_mask = MDP_TRANSP_NOP;
315 if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
316 req->alpha != MDP_ALPHA_NOP ||
317 HAS_ALPHA(req->src.format)) &&
318 (req->flags & MDP_ROT_90 &&
319 req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
320 int i;
321 unsigned int tiles = req->dst_rect.h / 16;
322 unsigned int remainder = req->dst_rect.h % 16;
323 req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
324 req->dst_rect.h = 16;
325 for (i = 0; i < tiles; i++) {
326 enable_mdp_irq(mdp, DL0_ROI_DONE);
327 ret = mdp_ppp_blit(mdp, req, src_file, src_start,
328 src_len, dst_file, dst_start,
329 dst_len);
330 if (ret)
331 goto err_bad_blit;
332 ret = mdp_ppp_wait(mdp);
333 if (ret)
334 goto err_wait_failed;
335 req->dst_rect.y += 16;
336 req->src_rect.x += req->src_rect.w;
337 }
338 if (!remainder)
339 goto end;
340 req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
341 req->dst_rect.h = remainder;
342 }
343 enable_mdp_irq(mdp, DL0_ROI_DONE);
344 ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
345 dst_start,
346 dst_len);
347 if (ret)
348 goto err_bad_blit;
349 ret = mdp_ppp_wait(mdp);
350 if (ret)
351 goto err_wait_failed;
352end:
353 put_img(src_file, dst_file);
354 mutex_unlock(&mdp_mutex);
355 return 0;
356err_bad_blit:
357 disable_mdp_irq(mdp, DL0_ROI_DONE);
358err_wait_failed:
359 put_img(src_file, dst_file);
360 mutex_unlock(&mdp_mutex);
361 return ret;
362}
363
364void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
365{
366 struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
367
368 disp_id &= 0xf;
369 mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
370}
371
372int register_mdp_client(struct class_interface *cint)
373{
374 if (!mdp_class) {
375 pr_err("mdp: no mdp_class when registering mdp client\n");
376 return -ENODEV;
377 }
378 cint->class = mdp_class;
379 return class_interface_register(cint);
380}
381
382#include "mdp_csc_table.h"
383#include "mdp_scale_tables.h"
384
385int mdp_probe(struct platform_device *pdev)
386{
387 struct resource *resource;
388 int ret;
389 int n;
390 struct mdp_info *mdp;
391
392 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
393 if (!resource) {
394 pr_err("mdp: can not get mdp mem resource!\n");
395 return -ENOMEM;
396 }
397
398 mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
399 if (!mdp)
400 return -ENOMEM;
401
402 mdp->irq = platform_get_irq(pdev, 0);
403 if (mdp->irq < 0) {
404 pr_err("mdp: can not get mdp irq\n");
405 ret = mdp->irq;
406 goto error_get_irq;
407 }
408
409 mdp->base = ioremap(resource->start,
410 resource->end - resource->start);
411 if (mdp->base == 0) {
412 printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
413 ret = -ENOMEM;
414 goto error_ioremap;
415 }
416
417 mdp->mdp_dev.dma = mdp_dma;
418 mdp->mdp_dev.dma_wait = mdp_dma_wait;
419 mdp->mdp_dev.blit = mdp_blit;
420 mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
421
422 clk = clk_get(&pdev->dev, "mdp_clk");
423 if (IS_ERR(clk)) {
424 printk(KERN_INFO "mdp: failed to get mdp clk");
425 return PTR_ERR(clk);
426 }
427
428 ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
429 if (ret)
430 goto error_request_irq;
431 disable_irq(mdp->irq);
432 mdp_irq_mask = 0;
433
434 /* debug interface write access */
435 mdp_writel(mdp, 1, 0x60);
436
437 mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
438 mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
439
440 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
441 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
442
443 for (n = 0; n < ARRAY_SIZE(csc_table); n++)
444 mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
445
446 /* clear up unused fg/main registers */
447 /* comp.plane 2&3 ystride */
448 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
449
450 /* unpacked pattern */
451 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
452 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
453 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
454 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
455 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
456 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
457 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
458 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
459 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
460
461 /* comp.plane 2 & 3 */
462 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
463 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
464
465 /* clear unused bg registers */
466 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
467 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
468 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
469 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
470 mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
471
472 for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
473 mdp_writel(mdp, mdp_upscale_table[n].val,
474 mdp_upscale_table[n].reg);
475
476 for (n = 0; n < 9; n++)
477 mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
478 mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
479 mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
480 mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
481
482 /* register mdp device */
483 mdp->mdp_dev.dev.parent = &pdev->dev;
484 mdp->mdp_dev.dev.class = mdp_class;
485
486 /* if you can remove the platform device you'd have to implement
487 * this:
488 mdp_dev.release = mdp_class; */
489
490 ret = device_register(&mdp->mdp_dev.dev);
491 if (ret)
492 goto error_device_register;
493 return 0;
494
495error_device_register:
496 free_irq(mdp->irq, mdp);
497error_request_irq:
498 iounmap(mdp->base);
499error_get_irq:
500error_ioremap:
501 kfree(mdp);
502 return ret;
503}
504
505static struct platform_driver msm_mdp_driver = {
506 .probe = mdp_probe,
507 .driver = {.name = "msm_mdp"},
508};
509
510static int __init mdp_init(void)
511{
512 mdp_class = class_create(THIS_MODULE, "msm_mdp");
513 if (IS_ERR(mdp_class)) {
514 printk(KERN_ERR "Error creating mdp class\n");
515 return PTR_ERR(mdp_class);
516 }
517 return platform_driver_register(&msm_mdp_driver);
518}
519
520subsys_initcall(mdp_init);
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
new file mode 100644
index 000000000000..d1cde30ead52
--- /dev/null
+++ b/drivers/video/msm/mdp_csc_table.h
@@ -0,0 +1,582 @@
1/* drivers/video/msm_fb/mdp_csc_table.h
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16static struct {
17 uint32_t reg;
18 uint32_t val;
19} csc_table[] = {
20 { 0x40400, 0x83 },
21 { 0x40404, 0x102 },
22 { 0x40408, 0x32 },
23 { 0x4040c, 0xffffffb5 },
24 { 0x40410, 0xffffff6c },
25 { 0x40414, 0xe1 },
26 { 0x40418, 0xe1 },
27 { 0x4041c, 0xffffff45 },
28 { 0x40420, 0xffffffdc },
29 { 0x40440, 0x254 },
30 { 0x40444, 0x0 },
31 { 0x40448, 0x331 },
32 { 0x4044c, 0x254 },
33 { 0x40450, 0xffffff38 },
34 { 0x40454, 0xfffffe61 },
35 { 0x40458, 0x254 },
36 { 0x4045c, 0x409 },
37 { 0x40460, 0x0 },
38 { 0x40480, 0x5d },
39 { 0x40484, 0x13a },
40 { 0x40488, 0x20 },
41 { 0x4048c, 0xffffffcd },
42 { 0x40490, 0xffffff54 },
43 { 0x40494, 0xe1 },
44 { 0x40498, 0xe1 },
45 { 0x4049c, 0xffffff35 },
46 { 0x404a0, 0xffffffec },
47 { 0x404c0, 0x254 },
48 { 0x404c4, 0x0 },
49 { 0x404c8, 0x396 },
50 { 0x404cc, 0x254 },
51 { 0x404d0, 0xffffff94 },
52 { 0x404d4, 0xfffffef0 },
53 { 0x404d8, 0x254 },
54 { 0x404dc, 0x43a },
55 { 0x404e0, 0x0 },
56 { 0x40500, 0x10 },
57 { 0x40504, 0x80 },
58 { 0x40508, 0x80 },
59 { 0x40540, 0x10 },
60 { 0x40544, 0x80 },
61 { 0x40548, 0x80 },
62 { 0x40580, 0x10 },
63 { 0x40584, 0xeb },
64 { 0x40588, 0x10 },
65 { 0x4058c, 0xf0 },
66 { 0x405c0, 0x10 },
67 { 0x405c4, 0xeb },
68 { 0x405c8, 0x10 },
69 { 0x405cc, 0xf0 },
70 { 0x40800, 0x0 },
71 { 0x40804, 0x151515 },
72 { 0x40808, 0x1d1d1d },
73 { 0x4080c, 0x232323 },
74 { 0x40810, 0x272727 },
75 { 0x40814, 0x2b2b2b },
76 { 0x40818, 0x2f2f2f },
77 { 0x4081c, 0x333333 },
78 { 0x40820, 0x363636 },
79 { 0x40824, 0x393939 },
80 { 0x40828, 0x3b3b3b },
81 { 0x4082c, 0x3e3e3e },
82 { 0x40830, 0x404040 },
83 { 0x40834, 0x434343 },
84 { 0x40838, 0x454545 },
85 { 0x4083c, 0x474747 },
86 { 0x40840, 0x494949 },
87 { 0x40844, 0x4b4b4b },
88 { 0x40848, 0x4d4d4d },
89 { 0x4084c, 0x4f4f4f },
90 { 0x40850, 0x515151 },
91 { 0x40854, 0x535353 },
92 { 0x40858, 0x555555 },
93 { 0x4085c, 0x565656 },
94 { 0x40860, 0x585858 },
95 { 0x40864, 0x5a5a5a },
96 { 0x40868, 0x5b5b5b },
97 { 0x4086c, 0x5d5d5d },
98 { 0x40870, 0x5e5e5e },
99 { 0x40874, 0x606060 },
100 { 0x40878, 0x616161 },
101 { 0x4087c, 0x636363 },
102 { 0x40880, 0x646464 },
103 { 0x40884, 0x666666 },
104 { 0x40888, 0x676767 },
105 { 0x4088c, 0x686868 },
106 { 0x40890, 0x6a6a6a },
107 { 0x40894, 0x6b6b6b },
108 { 0x40898, 0x6c6c6c },
109 { 0x4089c, 0x6e6e6e },
110 { 0x408a0, 0x6f6f6f },
111 { 0x408a4, 0x707070 },
112 { 0x408a8, 0x717171 },
113 { 0x408ac, 0x727272 },
114 { 0x408b0, 0x747474 },
115 { 0x408b4, 0x757575 },
116 { 0x408b8, 0x767676 },
117 { 0x408bc, 0x777777 },
118 { 0x408c0, 0x787878 },
119 { 0x408c4, 0x797979 },
120 { 0x408c8, 0x7a7a7a },
121 { 0x408cc, 0x7c7c7c },
122 { 0x408d0, 0x7d7d7d },
123 { 0x408d4, 0x7e7e7e },
124 { 0x408d8, 0x7f7f7f },
125 { 0x408dc, 0x808080 },
126 { 0x408e0, 0x818181 },
127 { 0x408e4, 0x828282 },
128 { 0x408e8, 0x838383 },
129 { 0x408ec, 0x848484 },
130 { 0x408f0, 0x858585 },
131 { 0x408f4, 0x868686 },
132 { 0x408f8, 0x878787 },
133 { 0x408fc, 0x888888 },
134 { 0x40900, 0x898989 },
135 { 0x40904, 0x8a8a8a },
136 { 0x40908, 0x8b8b8b },
137 { 0x4090c, 0x8c8c8c },
138 { 0x40910, 0x8d8d8d },
139 { 0x40914, 0x8e8e8e },
140 { 0x40918, 0x8f8f8f },
141 { 0x4091c, 0x8f8f8f },
142 { 0x40920, 0x909090 },
143 { 0x40924, 0x919191 },
144 { 0x40928, 0x929292 },
145 { 0x4092c, 0x939393 },
146 { 0x40930, 0x949494 },
147 { 0x40934, 0x959595 },
148 { 0x40938, 0x969696 },
149 { 0x4093c, 0x969696 },
150 { 0x40940, 0x979797 },
151 { 0x40944, 0x989898 },
152 { 0x40948, 0x999999 },
153 { 0x4094c, 0x9a9a9a },
154 { 0x40950, 0x9b9b9b },
155 { 0x40954, 0x9c9c9c },
156 { 0x40958, 0x9c9c9c },
157 { 0x4095c, 0x9d9d9d },
158 { 0x40960, 0x9e9e9e },
159 { 0x40964, 0x9f9f9f },
160 { 0x40968, 0xa0a0a0 },
161 { 0x4096c, 0xa0a0a0 },
162 { 0x40970, 0xa1a1a1 },
163 { 0x40974, 0xa2a2a2 },
164 { 0x40978, 0xa3a3a3 },
165 { 0x4097c, 0xa4a4a4 },
166 { 0x40980, 0xa4a4a4 },
167 { 0x40984, 0xa5a5a5 },
168 { 0x40988, 0xa6a6a6 },
169 { 0x4098c, 0xa7a7a7 },
170 { 0x40990, 0xa7a7a7 },
171 { 0x40994, 0xa8a8a8 },
172 { 0x40998, 0xa9a9a9 },
173 { 0x4099c, 0xaaaaaa },
174 { 0x409a0, 0xaaaaaa },
175 { 0x409a4, 0xababab },
176 { 0x409a8, 0xacacac },
177 { 0x409ac, 0xadadad },
178 { 0x409b0, 0xadadad },
179 { 0x409b4, 0xaeaeae },
180 { 0x409b8, 0xafafaf },
181 { 0x409bc, 0xafafaf },
182 { 0x409c0, 0xb0b0b0 },
183 { 0x409c4, 0xb1b1b1 },
184 { 0x409c8, 0xb2b2b2 },
185 { 0x409cc, 0xb2b2b2 },
186 { 0x409d0, 0xb3b3b3 },
187 { 0x409d4, 0xb4b4b4 },
188 { 0x409d8, 0xb4b4b4 },
189 { 0x409dc, 0xb5b5b5 },
190 { 0x409e0, 0xb6b6b6 },
191 { 0x409e4, 0xb6b6b6 },
192 { 0x409e8, 0xb7b7b7 },
193 { 0x409ec, 0xb8b8b8 },
194 { 0x409f0, 0xb8b8b8 },
195 { 0x409f4, 0xb9b9b9 },
196 { 0x409f8, 0xbababa },
197 { 0x409fc, 0xbababa },
198 { 0x40a00, 0xbbbbbb },
199 { 0x40a04, 0xbcbcbc },
200 { 0x40a08, 0xbcbcbc },
201 { 0x40a0c, 0xbdbdbd },
202 { 0x40a10, 0xbebebe },
203 { 0x40a14, 0xbebebe },
204 { 0x40a18, 0xbfbfbf },
205 { 0x40a1c, 0xc0c0c0 },
206 { 0x40a20, 0xc0c0c0 },
207 { 0x40a24, 0xc1c1c1 },
208 { 0x40a28, 0xc1c1c1 },
209 { 0x40a2c, 0xc2c2c2 },
210 { 0x40a30, 0xc3c3c3 },
211 { 0x40a34, 0xc3c3c3 },
212 { 0x40a38, 0xc4c4c4 },
213 { 0x40a3c, 0xc5c5c5 },
214 { 0x40a40, 0xc5c5c5 },
215 { 0x40a44, 0xc6c6c6 },
216 { 0x40a48, 0xc6c6c6 },
217 { 0x40a4c, 0xc7c7c7 },
218 { 0x40a50, 0xc8c8c8 },
219 { 0x40a54, 0xc8c8c8 },
220 { 0x40a58, 0xc9c9c9 },
221 { 0x40a5c, 0xc9c9c9 },
222 { 0x40a60, 0xcacaca },
223 { 0x40a64, 0xcbcbcb },
224 { 0x40a68, 0xcbcbcb },
225 { 0x40a6c, 0xcccccc },
226 { 0x40a70, 0xcccccc },
227 { 0x40a74, 0xcdcdcd },
228 { 0x40a78, 0xcecece },
229 { 0x40a7c, 0xcecece },
230 { 0x40a80, 0xcfcfcf },
231 { 0x40a84, 0xcfcfcf },
232 { 0x40a88, 0xd0d0d0 },
233 { 0x40a8c, 0xd0d0d0 },
234 { 0x40a90, 0xd1d1d1 },
235 { 0x40a94, 0xd2d2d2 },
236 { 0x40a98, 0xd2d2d2 },
237 { 0x40a9c, 0xd3d3d3 },
238 { 0x40aa0, 0xd3d3d3 },
239 { 0x40aa4, 0xd4d4d4 },
240 { 0x40aa8, 0xd4d4d4 },
241 { 0x40aac, 0xd5d5d5 },
242 { 0x40ab0, 0xd6d6d6 },
243 { 0x40ab4, 0xd6d6d6 },
244 { 0x40ab8, 0xd7d7d7 },
245 { 0x40abc, 0xd7d7d7 },
246 { 0x40ac0, 0xd8d8d8 },
247 { 0x40ac4, 0xd8d8d8 },
248 { 0x40ac8, 0xd9d9d9 },
249 { 0x40acc, 0xd9d9d9 },
250 { 0x40ad0, 0xdadada },
251 { 0x40ad4, 0xdbdbdb },
252 { 0x40ad8, 0xdbdbdb },
253 { 0x40adc, 0xdcdcdc },
254 { 0x40ae0, 0xdcdcdc },
255 { 0x40ae4, 0xdddddd },
256 { 0x40ae8, 0xdddddd },
257 { 0x40aec, 0xdedede },
258 { 0x40af0, 0xdedede },
259 { 0x40af4, 0xdfdfdf },
260 { 0x40af8, 0xdfdfdf },
261 { 0x40afc, 0xe0e0e0 },
262 { 0x40b00, 0xe0e0e0 },
263 { 0x40b04, 0xe1e1e1 },
264 { 0x40b08, 0xe1e1e1 },
265 { 0x40b0c, 0xe2e2e2 },
266 { 0x40b10, 0xe3e3e3 },
267 { 0x40b14, 0xe3e3e3 },
268 { 0x40b18, 0xe4e4e4 },
269 { 0x40b1c, 0xe4e4e4 },
270 { 0x40b20, 0xe5e5e5 },
271 { 0x40b24, 0xe5e5e5 },
272 { 0x40b28, 0xe6e6e6 },
273 { 0x40b2c, 0xe6e6e6 },
274 { 0x40b30, 0xe7e7e7 },
275 { 0x40b34, 0xe7e7e7 },
276 { 0x40b38, 0xe8e8e8 },
277 { 0x40b3c, 0xe8e8e8 },
278 { 0x40b40, 0xe9e9e9 },
279 { 0x40b44, 0xe9e9e9 },
280 { 0x40b48, 0xeaeaea },
281 { 0x40b4c, 0xeaeaea },
282 { 0x40b50, 0xebebeb },
283 { 0x40b54, 0xebebeb },
284 { 0x40b58, 0xececec },
285 { 0x40b5c, 0xececec },
286 { 0x40b60, 0xededed },
287 { 0x40b64, 0xededed },
288 { 0x40b68, 0xeeeeee },
289 { 0x40b6c, 0xeeeeee },
290 { 0x40b70, 0xefefef },
291 { 0x40b74, 0xefefef },
292 { 0x40b78, 0xf0f0f0 },
293 { 0x40b7c, 0xf0f0f0 },
294 { 0x40b80, 0xf1f1f1 },
295 { 0x40b84, 0xf1f1f1 },
296 { 0x40b88, 0xf2f2f2 },
297 { 0x40b8c, 0xf2f2f2 },
298 { 0x40b90, 0xf2f2f2 },
299 { 0x40b94, 0xf3f3f3 },
300 { 0x40b98, 0xf3f3f3 },
301 { 0x40b9c, 0xf4f4f4 },
302 { 0x40ba0, 0xf4f4f4 },
303 { 0x40ba4, 0xf5f5f5 },
304 { 0x40ba8, 0xf5f5f5 },
305 { 0x40bac, 0xf6f6f6 },
306 { 0x40bb0, 0xf6f6f6 },
307 { 0x40bb4, 0xf7f7f7 },
308 { 0x40bb8, 0xf7f7f7 },
309 { 0x40bbc, 0xf8f8f8 },
310 { 0x40bc0, 0xf8f8f8 },
311 { 0x40bc4, 0xf9f9f9 },
312 { 0x40bc8, 0xf9f9f9 },
313 { 0x40bcc, 0xfafafa },
314 { 0x40bd0, 0xfafafa },
315 { 0x40bd4, 0xfafafa },
316 { 0x40bd8, 0xfbfbfb },
317 { 0x40bdc, 0xfbfbfb },
318 { 0x40be0, 0xfcfcfc },
319 { 0x40be4, 0xfcfcfc },
320 { 0x40be8, 0xfdfdfd },
321 { 0x40bec, 0xfdfdfd },
322 { 0x40bf0, 0xfefefe },
323 { 0x40bf4, 0xfefefe },
324 { 0x40bf8, 0xffffff },
325 { 0x40bfc, 0xffffff },
326 { 0x40c00, 0x0 },
327 { 0x40c04, 0x0 },
328 { 0x40c08, 0x0 },
329 { 0x40c0c, 0x0 },
330 { 0x40c10, 0x0 },
331 { 0x40c14, 0x0 },
332 { 0x40c18, 0x0 },
333 { 0x40c1c, 0x0 },
334 { 0x40c20, 0x0 },
335 { 0x40c24, 0x0 },
336 { 0x40c28, 0x0 },
337 { 0x40c2c, 0x0 },
338 { 0x40c30, 0x0 },
339 { 0x40c34, 0x0 },
340 { 0x40c38, 0x0 },
341 { 0x40c3c, 0x0 },
342 { 0x40c40, 0x10101 },
343 { 0x40c44, 0x10101 },
344 { 0x40c48, 0x10101 },
345 { 0x40c4c, 0x10101 },
346 { 0x40c50, 0x10101 },
347 { 0x40c54, 0x10101 },
348 { 0x40c58, 0x10101 },
349 { 0x40c5c, 0x10101 },
350 { 0x40c60, 0x10101 },
351 { 0x40c64, 0x10101 },
352 { 0x40c68, 0x20202 },
353 { 0x40c6c, 0x20202 },
354 { 0x40c70, 0x20202 },
355 { 0x40c74, 0x20202 },
356 { 0x40c78, 0x20202 },
357 { 0x40c7c, 0x20202 },
358 { 0x40c80, 0x30303 },
359 { 0x40c84, 0x30303 },
360 { 0x40c88, 0x30303 },
361 { 0x40c8c, 0x30303 },
362 { 0x40c90, 0x30303 },
363 { 0x40c94, 0x40404 },
364 { 0x40c98, 0x40404 },
365 { 0x40c9c, 0x40404 },
366 { 0x40ca0, 0x40404 },
367 { 0x40ca4, 0x40404 },
368 { 0x40ca8, 0x50505 },
369 { 0x40cac, 0x50505 },
370 { 0x40cb0, 0x50505 },
371 { 0x40cb4, 0x50505 },
372 { 0x40cb8, 0x60606 },
373 { 0x40cbc, 0x60606 },
374 { 0x40cc0, 0x60606 },
375 { 0x40cc4, 0x70707 },
376 { 0x40cc8, 0x70707 },
377 { 0x40ccc, 0x70707 },
378 { 0x40cd0, 0x70707 },
379 { 0x40cd4, 0x80808 },
380 { 0x40cd8, 0x80808 },
381 { 0x40cdc, 0x80808 },
382 { 0x40ce0, 0x90909 },
383 { 0x40ce4, 0x90909 },
384 { 0x40ce8, 0xa0a0a },
385 { 0x40cec, 0xa0a0a },
386 { 0x40cf0, 0xa0a0a },
387 { 0x40cf4, 0xb0b0b },
388 { 0x40cf8, 0xb0b0b },
389 { 0x40cfc, 0xb0b0b },
390 { 0x40d00, 0xc0c0c },
391 { 0x40d04, 0xc0c0c },
392 { 0x40d08, 0xd0d0d },
393 { 0x40d0c, 0xd0d0d },
394 { 0x40d10, 0xe0e0e },
395 { 0x40d14, 0xe0e0e },
396 { 0x40d18, 0xe0e0e },
397 { 0x40d1c, 0xf0f0f },
398 { 0x40d20, 0xf0f0f },
399 { 0x40d24, 0x101010 },
400 { 0x40d28, 0x101010 },
401 { 0x40d2c, 0x111111 },
402 { 0x40d30, 0x111111 },
403 { 0x40d34, 0x121212 },
404 { 0x40d38, 0x121212 },
405 { 0x40d3c, 0x131313 },
406 { 0x40d40, 0x131313 },
407 { 0x40d44, 0x141414 },
408 { 0x40d48, 0x151515 },
409 { 0x40d4c, 0x151515 },
410 { 0x40d50, 0x161616 },
411 { 0x40d54, 0x161616 },
412 { 0x40d58, 0x171717 },
413 { 0x40d5c, 0x171717 },
414 { 0x40d60, 0x181818 },
415 { 0x40d64, 0x191919 },
416 { 0x40d68, 0x191919 },
417 { 0x40d6c, 0x1a1a1a },
418 { 0x40d70, 0x1b1b1b },
419 { 0x40d74, 0x1b1b1b },
420 { 0x40d78, 0x1c1c1c },
421 { 0x40d7c, 0x1c1c1c },
422 { 0x40d80, 0x1d1d1d },
423 { 0x40d84, 0x1e1e1e },
424 { 0x40d88, 0x1f1f1f },
425 { 0x40d8c, 0x1f1f1f },
426 { 0x40d90, 0x202020 },
427 { 0x40d94, 0x212121 },
428 { 0x40d98, 0x212121 },
429 { 0x40d9c, 0x222222 },
430 { 0x40da0, 0x232323 },
431 { 0x40da4, 0x242424 },
432 { 0x40da8, 0x242424 },
433 { 0x40dac, 0x252525 },
434 { 0x40db0, 0x262626 },
435 { 0x40db4, 0x272727 },
436 { 0x40db8, 0x272727 },
437 { 0x40dbc, 0x282828 },
438 { 0x40dc0, 0x292929 },
439 { 0x40dc4, 0x2a2a2a },
440 { 0x40dc8, 0x2b2b2b },
441 { 0x40dcc, 0x2c2c2c },
442 { 0x40dd0, 0x2c2c2c },
443 { 0x40dd4, 0x2d2d2d },
444 { 0x40dd8, 0x2e2e2e },
445 { 0x40ddc, 0x2f2f2f },
446 { 0x40de0, 0x303030 },
447 { 0x40de4, 0x313131 },
448 { 0x40de8, 0x323232 },
449 { 0x40dec, 0x333333 },
450 { 0x40df0, 0x333333 },
451 { 0x40df4, 0x343434 },
452 { 0x40df8, 0x353535 },
453 { 0x40dfc, 0x363636 },
454 { 0x40e00, 0x373737 },
455 { 0x40e04, 0x383838 },
456 { 0x40e08, 0x393939 },
457 { 0x40e0c, 0x3a3a3a },
458 { 0x40e10, 0x3b3b3b },
459 { 0x40e14, 0x3c3c3c },
460 { 0x40e18, 0x3d3d3d },
461 { 0x40e1c, 0x3e3e3e },
462 { 0x40e20, 0x3f3f3f },
463 { 0x40e24, 0x404040 },
464 { 0x40e28, 0x414141 },
465 { 0x40e2c, 0x424242 },
466 { 0x40e30, 0x434343 },
467 { 0x40e34, 0x444444 },
468 { 0x40e38, 0x464646 },
469 { 0x40e3c, 0x474747 },
470 { 0x40e40, 0x484848 },
471 { 0x40e44, 0x494949 },
472 { 0x40e48, 0x4a4a4a },
473 { 0x40e4c, 0x4b4b4b },
474 { 0x40e50, 0x4c4c4c },
475 { 0x40e54, 0x4d4d4d },
476 { 0x40e58, 0x4f4f4f },
477 { 0x40e5c, 0x505050 },
478 { 0x40e60, 0x515151 },
479 { 0x40e64, 0x525252 },
480 { 0x40e68, 0x535353 },
481 { 0x40e6c, 0x545454 },
482 { 0x40e70, 0x565656 },
483 { 0x40e74, 0x575757 },
484 { 0x40e78, 0x585858 },
485 { 0x40e7c, 0x595959 },
486 { 0x40e80, 0x5b5b5b },
487 { 0x40e84, 0x5c5c5c },
488 { 0x40e88, 0x5d5d5d },
489 { 0x40e8c, 0x5e5e5e },
490 { 0x40e90, 0x606060 },
491 { 0x40e94, 0x616161 },
492 { 0x40e98, 0x626262 },
493 { 0x40e9c, 0x646464 },
494 { 0x40ea0, 0x656565 },
495 { 0x40ea4, 0x666666 },
496 { 0x40ea8, 0x686868 },
497 { 0x40eac, 0x696969 },
498 { 0x40eb0, 0x6a6a6a },
499 { 0x40eb4, 0x6c6c6c },
500 { 0x40eb8, 0x6d6d6d },
501 { 0x40ebc, 0x6f6f6f },
502 { 0x40ec0, 0x707070 },
503 { 0x40ec4, 0x717171 },
504 { 0x40ec8, 0x737373 },
505 { 0x40ecc, 0x747474 },
506 { 0x40ed0, 0x767676 },
507 { 0x40ed4, 0x777777 },
508 { 0x40ed8, 0x797979 },
509 { 0x40edc, 0x7a7a7a },
510 { 0x40ee0, 0x7c7c7c },
511 { 0x40ee4, 0x7d7d7d },
512 { 0x40ee8, 0x7f7f7f },
513 { 0x40eec, 0x808080 },
514 { 0x40ef0, 0x828282 },
515 { 0x40ef4, 0x838383 },
516 { 0x40ef8, 0x858585 },
517 { 0x40efc, 0x868686 },
518 { 0x40f00, 0x888888 },
519 { 0x40f04, 0x898989 },
520 { 0x40f08, 0x8b8b8b },
521 { 0x40f0c, 0x8d8d8d },
522 { 0x40f10, 0x8e8e8e },
523 { 0x40f14, 0x909090 },
524 { 0x40f18, 0x919191 },
525 { 0x40f1c, 0x939393 },
526 { 0x40f20, 0x959595 },
527 { 0x40f24, 0x969696 },
528 { 0x40f28, 0x989898 },
529 { 0x40f2c, 0x9a9a9a },
530 { 0x40f30, 0x9b9b9b },
531 { 0x40f34, 0x9d9d9d },
532 { 0x40f38, 0x9f9f9f },
533 { 0x40f3c, 0xa1a1a1 },
534 { 0x40f40, 0xa2a2a2 },
535 { 0x40f44, 0xa4a4a4 },
536 { 0x40f48, 0xa6a6a6 },
537 { 0x40f4c, 0xa7a7a7 },
538 { 0x40f50, 0xa9a9a9 },
539 { 0x40f54, 0xababab },
540 { 0x40f58, 0xadadad },
541 { 0x40f5c, 0xafafaf },
542 { 0x40f60, 0xb0b0b0 },
543 { 0x40f64, 0xb2b2b2 },
544 { 0x40f68, 0xb4b4b4 },
545 { 0x40f6c, 0xb6b6b6 },
546 { 0x40f70, 0xb8b8b8 },
547 { 0x40f74, 0xbababa },
548 { 0x40f78, 0xbbbbbb },
549 { 0x40f7c, 0xbdbdbd },
550 { 0x40f80, 0xbfbfbf },
551 { 0x40f84, 0xc1c1c1 },
552 { 0x40f88, 0xc3c3c3 },
553 { 0x40f8c, 0xc5c5c5 },
554 { 0x40f90, 0xc7c7c7 },
555 { 0x40f94, 0xc9c9c9 },
556 { 0x40f98, 0xcbcbcb },
557 { 0x40f9c, 0xcdcdcd },
558 { 0x40fa0, 0xcfcfcf },
559 { 0x40fa4, 0xd1d1d1 },
560 { 0x40fa8, 0xd3d3d3 },
561 { 0x40fac, 0xd5d5d5 },
562 { 0x40fb0, 0xd7d7d7 },
563 { 0x40fb4, 0xd9d9d9 },
564 { 0x40fb8, 0xdbdbdb },
565 { 0x40fbc, 0xdddddd },
566 { 0x40fc0, 0xdfdfdf },
567 { 0x40fc4, 0xe1e1e1 },
568 { 0x40fc8, 0xe3e3e3 },
569 { 0x40fcc, 0xe5e5e5 },
570 { 0x40fd0, 0xe7e7e7 },
571 { 0x40fd4, 0xe9e9e9 },
572 { 0x40fd8, 0xebebeb },
573 { 0x40fdc, 0xeeeeee },
574 { 0x40fe0, 0xf0f0f0 },
575 { 0x40fe4, 0xf2f2f2 },
576 { 0x40fe8, 0xf4f4f4 },
577 { 0x40fec, 0xf6f6f6 },
578 { 0x40ff0, 0xf8f8f8 },
579 { 0x40ff4, 0xfbfbfb },
580 { 0x40ff8, 0xfdfdfd },
581 { 0x40ffc, 0xffffff },
582};
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
new file mode 100644
index 000000000000..4e3deb4e592b
--- /dev/null
+++ b/drivers/video/msm/mdp_hw.h
@@ -0,0 +1,621 @@
1/* drivers/video/msm_fb/mdp_hw.h
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#ifndef _MDP_HW_H_
16#define _MDP_HW_H_
17
18#include <mach/msm_iomap.h>
19#include <mach/msm_fb.h>
20
21struct mdp_info {
22 struct mdp_device mdp_dev;
23 char * __iomem base;
24 int irq;
25};
26struct mdp_blit_req;
27struct mdp_device;
28int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
29 struct file *src_file, unsigned long src_start,
30 unsigned long src_len, struct file *dst_file,
31 unsigned long dst_start, unsigned long dst_len);
32#define mdp_writel(mdp, value, offset) writel(value, mdp->base + offset)
33#define mdp_readl(mdp, offset) readl(mdp->base + offset)
34
35#define MDP_SYNC_CONFIG_0 (0x00000)
36#define MDP_SYNC_CONFIG_1 (0x00004)
37#define MDP_SYNC_CONFIG_2 (0x00008)
38#define MDP_SYNC_STATUS_0 (0x0000c)
39#define MDP_SYNC_STATUS_1 (0x00010)
40#define MDP_SYNC_STATUS_2 (0x00014)
41#define MDP_SYNC_THRESH_0 (0x00018)
42#define MDP_SYNC_THRESH_1 (0x0001c)
43#define MDP_INTR_ENABLE (0x00020)
44#define MDP_INTR_STATUS (0x00024)
45#define MDP_INTR_CLEAR (0x00028)
46#define MDP_DISPLAY0_START (0x00030)
47#define MDP_DISPLAY1_START (0x00034)
48#define MDP_DISPLAY_STATUS (0x00038)
49#define MDP_EBI2_LCD0 (0x0003c)
50#define MDP_EBI2_LCD1 (0x00040)
51#define MDP_DISPLAY0_ADDR (0x00054)
52#define MDP_DISPLAY1_ADDR (0x00058)
53#define MDP_EBI2_PORTMAP_MODE (0x0005c)
54#define MDP_MODE (0x00060)
55#define MDP_TV_OUT_STATUS (0x00064)
56#define MDP_HW_VERSION (0x00070)
57#define MDP_SW_RESET (0x00074)
58#define MDP_AXI_ERROR_MASTER_STOP (0x00078)
59#define MDP_SEL_CLK_OR_HCLK_TEST_BUS (0x0007c)
60#define MDP_PRIMARY_VSYNC_OUT_CTRL (0x00080)
61#define MDP_SECONDARY_VSYNC_OUT_CTRL (0x00084)
62#define MDP_EXTERNAL_VSYNC_OUT_CTRL (0x00088)
63#define MDP_VSYNC_CTRL (0x0008c)
64#define MDP_CGC_EN (0x00100)
65#define MDP_CMD_STATUS (0x10008)
66#define MDP_PROFILE_EN (0x10010)
67#define MDP_PROFILE_COUNT (0x10014)
68#define MDP_DMA_START (0x10044)
69#define MDP_FULL_BYPASS_WORD0 (0x10100)
70#define MDP_FULL_BYPASS_WORD1 (0x10104)
71#define MDP_COMMAND_CONFIG (0x10104)
72#define MDP_FULL_BYPASS_WORD2 (0x10108)
73#define MDP_FULL_BYPASS_WORD3 (0x1010c)
74#define MDP_FULL_BYPASS_WORD4 (0x10110)
75#define MDP_FULL_BYPASS_WORD6 (0x10118)
76#define MDP_FULL_BYPASS_WORD7 (0x1011c)
77#define MDP_FULL_BYPASS_WORD8 (0x10120)
78#define MDP_FULL_BYPASS_WORD9 (0x10124)
79#define MDP_PPP_SOURCE_CONFIG (0x10124)
80#define MDP_FULL_BYPASS_WORD10 (0x10128)
81#define MDP_FULL_BYPASS_WORD11 (0x1012c)
82#define MDP_FULL_BYPASS_WORD12 (0x10130)
83#define MDP_FULL_BYPASS_WORD13 (0x10134)
84#define MDP_FULL_BYPASS_WORD14 (0x10138)
85#define MDP_PPP_OPERATION_CONFIG (0x10138)
86#define MDP_FULL_BYPASS_WORD15 (0x1013c)
87#define MDP_FULL_BYPASS_WORD16 (0x10140)
88#define MDP_FULL_BYPASS_WORD17 (0x10144)
89#define MDP_FULL_BYPASS_WORD18 (0x10148)
90#define MDP_FULL_BYPASS_WORD19 (0x1014c)
91#define MDP_FULL_BYPASS_WORD20 (0x10150)
92#define MDP_PPP_DESTINATION_CONFIG (0x10150)
93#define MDP_FULL_BYPASS_WORD21 (0x10154)
94#define MDP_FULL_BYPASS_WORD22 (0x10158)
95#define MDP_FULL_BYPASS_WORD23 (0x1015c)
96#define MDP_FULL_BYPASS_WORD24 (0x10160)
97#define MDP_FULL_BYPASS_WORD25 (0x10164)
98#define MDP_FULL_BYPASS_WORD26 (0x10168)
99#define MDP_FULL_BYPASS_WORD27 (0x1016c)
100#define MDP_FULL_BYPASS_WORD29 (0x10174)
101#define MDP_FULL_BYPASS_WORD30 (0x10178)
102#define MDP_FULL_BYPASS_WORD31 (0x1017c)
103#define MDP_FULL_BYPASS_WORD32 (0x10180)
104#define MDP_DMA_CONFIG (0x10180)
105#define MDP_FULL_BYPASS_WORD33 (0x10184)
106#define MDP_FULL_BYPASS_WORD34 (0x10188)
107#define MDP_FULL_BYPASS_WORD35 (0x1018c)
108#define MDP_FULL_BYPASS_WORD37 (0x10194)
109#define MDP_FULL_BYPASS_WORD39 (0x1019c)
110#define MDP_FULL_BYPASS_WORD40 (0x101a0)
111#define MDP_FULL_BYPASS_WORD41 (0x101a4)
112#define MDP_FULL_BYPASS_WORD43 (0x101ac)
113#define MDP_FULL_BYPASS_WORD46 (0x101b8)
114#define MDP_FULL_BYPASS_WORD47 (0x101bc)
115#define MDP_FULL_BYPASS_WORD48 (0x101c0)
116#define MDP_FULL_BYPASS_WORD49 (0x101c4)
117#define MDP_FULL_BYPASS_WORD50 (0x101c8)
118#define MDP_FULL_BYPASS_WORD51 (0x101cc)
119#define MDP_FULL_BYPASS_WORD52 (0x101d0)
120#define MDP_FULL_BYPASS_WORD53 (0x101d4)
121#define MDP_FULL_BYPASS_WORD54 (0x101d8)
122#define MDP_FULL_BYPASS_WORD55 (0x101dc)
123#define MDP_FULL_BYPASS_WORD56 (0x101e0)
124#define MDP_FULL_BYPASS_WORD57 (0x101e4)
125#define MDP_FULL_BYPASS_WORD58 (0x101e8)
126#define MDP_FULL_BYPASS_WORD59 (0x101ec)
127#define MDP_FULL_BYPASS_WORD60 (0x101f0)
128#define MDP_VSYNC_THRESHOLD (0x101f0)
129#define MDP_FULL_BYPASS_WORD61 (0x101f4)
130#define MDP_FULL_BYPASS_WORD62 (0x101f8)
131#define MDP_FULL_BYPASS_WORD63 (0x101fc)
132#define MDP_TFETCH_TEST_MODE (0x20004)
133#define MDP_TFETCH_STATUS (0x20008)
134#define MDP_TFETCH_TILE_COUNT (0x20010)
135#define MDP_TFETCH_FETCH_COUNT (0x20014)
136#define MDP_TFETCH_CONSTANT_COLOR (0x20040)
137#define MDP_CSC_BYPASS (0x40004)
138#define MDP_SCALE_COEFF_LSB (0x5fffc)
139#define MDP_TV_OUT_CTL (0xc0000)
140#define MDP_TV_OUT_FIR_COEFF (0xc0004)
141#define MDP_TV_OUT_BUF_ADDR (0xc0008)
142#define MDP_TV_OUT_CC_DATA (0xc000c)
143#define MDP_TV_OUT_SOBEL (0xc0010)
144#define MDP_TV_OUT_Y_CLAMP (0xc0018)
145#define MDP_TV_OUT_CB_CLAMP (0xc001c)
146#define MDP_TV_OUT_CR_CLAMP (0xc0020)
147#define MDP_TEST_MODE_CLK (0xd0000)
148#define MDP_TEST_MISR_RESET_CLK (0xd0004)
149#define MDP_TEST_EXPORT_MISR_CLK (0xd0008)
150#define MDP_TEST_MISR_CURR_VAL_CLK (0xd000c)
151#define MDP_TEST_MODE_HCLK (0xd0100)
152#define MDP_TEST_MISR_RESET_HCLK (0xd0104)
153#define MDP_TEST_EXPORT_MISR_HCLK (0xd0108)
154#define MDP_TEST_MISR_CURR_VAL_HCLK (0xd010c)
155#define MDP_TEST_MODE_DCLK (0xd0200)
156#define MDP_TEST_MISR_RESET_DCLK (0xd0204)
157#define MDP_TEST_EXPORT_MISR_DCLK (0xd0208)
158#define MDP_TEST_MISR_CURR_VAL_DCLK (0xd020c)
159#define MDP_TEST_CAPTURED_DCLK (0xd0210)
160#define MDP_TEST_MISR_CAPT_VAL_DCLK (0xd0214)
161#define MDP_LCDC_CTL (0xe0000)
162#define MDP_LCDC_HSYNC_CTL (0xe0004)
163#define MDP_LCDC_VSYNC_CTL (0xe0008)
164#define MDP_LCDC_ACTIVE_HCTL (0xe000c)
165#define MDP_LCDC_ACTIVE_VCTL (0xe0010)
166#define MDP_LCDC_BORDER_CLR (0xe0014)
167#define MDP_LCDC_H_BLANK (0xe0018)
168#define MDP_LCDC_V_BLANK (0xe001c)
169#define MDP_LCDC_UNDERFLOW_CLR (0xe0020)
170#define MDP_LCDC_HSYNC_SKEW (0xe0024)
171#define MDP_LCDC_TEST_CTL (0xe0028)
172#define MDP_LCDC_LINE_IRQ (0xe002c)
173#define MDP_LCDC_CTL_POLARITY (0xe0030)
174#define MDP_LCDC_DMA_CONFIG (0xe1000)
175#define MDP_LCDC_DMA_SIZE (0xe1004)
176#define MDP_LCDC_DMA_IBUF_ADDR (0xe1008)
177#define MDP_LCDC_DMA_IBUF_Y_STRIDE (0xe100c)
178
179
180#define MDP_DMA2_TERM 0x1
181#define MDP_DMA3_TERM 0x2
182#define MDP_PPP_TERM 0x3
183
184/* MDP_INTR_ENABLE */
185#define DL0_ROI_DONE (1<<0)
186#define DL1_ROI_DONE (1<<1)
187#define DL0_DMA2_TERM_DONE (1<<2)
188#define DL1_DMA2_TERM_DONE (1<<3)
189#define DL0_PPP_TERM_DONE (1<<4)
190#define DL1_PPP_TERM_DONE (1<<5)
191#define TV_OUT_DMA3_DONE (1<<6)
192#define TV_ENC_UNDERRUN (1<<7)
193#define DL0_FETCH_DONE (1<<11)
194#define DL1_FETCH_DONE (1<<12)
195
196#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \
197 DL1_ROI_DONE| \
198 DL0_PPP_TERM_DONE| \
199 DL1_PPP_TERM_DONE)
200
201#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \
202 DL1_ROI_DONE| \
203 DL0_DMA2_TERM_DONE| \
204 DL1_DMA2_TERM_DONE| \
205 DL0_PPP_TERM_DONE| \
206 DL1_PPP_TERM_DONE| \
207 DL0_FETCH_DONE| \
208 DL1_FETCH_DONE| \
209 TV_ENC_UNDERRUN)
210
211#define MDP_TOP_LUMA 16
212#define MDP_TOP_CHROMA 0
213#define MDP_BOTTOM_LUMA 19
214#define MDP_BOTTOM_CHROMA 3
215#define MDP_LEFT_LUMA 22
216#define MDP_LEFT_CHROMA 6
217#define MDP_RIGHT_LUMA 25
218#define MDP_RIGHT_CHROMA 9
219
220#define CLR_G 0x0
221#define CLR_B 0x1
222#define CLR_R 0x2
223#define CLR_ALPHA 0x3
224
225#define CLR_Y CLR_G
226#define CLR_CB CLR_B
227#define CLR_CR CLR_R
228
229/* from lsb to msb */
230#define MDP_GET_PACK_PATTERN(a, x, y, z, bit) \
231 (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
232
233/* MDP_SYNC_CONFIG_0/1/2 */
234#define MDP_SYNCFG_HGT_LOC 22
235#define MDP_SYNCFG_VSYNC_EXT_EN (1<<21)
236#define MDP_SYNCFG_VSYNC_INT_EN (1<<20)
237
238/* MDP_SYNC_THRESH_0 */
239#define MDP_PRIM_BELOW_LOC 0
240#define MDP_PRIM_ABOVE_LOC 8
241
242/* MDP_{PRIMARY,SECONDARY,EXTERNAL}_VSYNC_OUT_CRL */
243#define VSYNC_PULSE_EN (1<<31)
244#define VSYNC_PULSE_INV (1<<30)
245
246/* MDP_VSYNC_CTRL */
247#define DISP0_VSYNC_MAP_VSYNC0 0
248#define DISP0_VSYNC_MAP_VSYNC1 (1<<0)
249#define DISP0_VSYNC_MAP_VSYNC2 ((1<<0)|(1<<1))
250
251#define DISP1_VSYNC_MAP_VSYNC0 0
252#define DISP1_VSYNC_MAP_VSYNC1 (1<<2)
253#define DISP1_VSYNC_MAP_VSYNC2 ((1<<2)|(1<<3))
254
255#define PRIMARY_LCD_SYNC_EN (1<<4)
256#define PRIMARY_LCD_SYNC_DISABLE 0
257
258#define SECONDARY_LCD_SYNC_EN (1<<5)
259#define SECONDARY_LCD_SYNC_DISABLE 0
260
261#define EXTERNAL_LCD_SYNC_EN (1<<6)
262#define EXTERNAL_LCD_SYNC_DISABLE 0
263
264/* MDP_VSYNC_THRESHOLD / MDP_FULL_BYPASS_WORD60 */
265#define VSYNC_THRESHOLD_ABOVE_LOC 0
266#define VSYNC_THRESHOLD_BELOW_LOC 16
267#define VSYNC_ANTI_TEAR_EN (1<<31)
268
269/* MDP_COMMAND_CONFIG / MDP_FULL_BYPASS_WORD1 */
270#define MDP_CMD_DBGBUS_EN (1<<0)
271
272/* MDP_PPP_SOURCE_CONFIG / MDP_FULL_BYPASS_WORD9&53 */
273#define PPP_SRC_C0G_8BIT ((1<<1)|(1<<0))
274#define PPP_SRC_C1B_8BIT ((1<<3)|(1<<2))
275#define PPP_SRC_C2R_8BIT ((1<<5)|(1<<4))
276#define PPP_SRC_C3A_8BIT ((1<<7)|(1<<6))
277
278#define PPP_SRC_C0G_6BIT (1<<1)
279#define PPP_SRC_C1B_6BIT (1<<3)
280#define PPP_SRC_C2R_6BIT (1<<5)
281
282#define PPP_SRC_C0G_5BIT (1<<0)
283#define PPP_SRC_C1B_5BIT (1<<2)
284#define PPP_SRC_C2R_5BIT (1<<4)
285
286#define PPP_SRC_C3ALPHA_EN (1<<8)
287
288#define PPP_SRC_BPP_1BYTES 0
289#define PPP_SRC_BPP_2BYTES (1<<9)
290#define PPP_SRC_BPP_3BYTES (1<<10)
291#define PPP_SRC_BPP_4BYTES ((1<<10)|(1<<9))
292
293#define PPP_SRC_BPP_ROI_ODD_X (1<<11)
294#define PPP_SRC_BPP_ROI_ODD_Y (1<<12)
295#define PPP_SRC_INTERLVD_2COMPONENTS (1<<13)
296#define PPP_SRC_INTERLVD_3COMPONENTS (1<<14)
297#define PPP_SRC_INTERLVD_4COMPONENTS ((1<<14)|(1<<13))
298
299
300/* RGB666 unpack format
301** TIGHT means R6+G6+B6 together
302** LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
303** or 2+R6 +2+G6 +2+B6 (with LSB)
304*/
305#define PPP_SRC_PACK_TIGHT (1<<17)
306#define PPP_SRC_PACK_LOOSE 0
307#define PPP_SRC_PACK_ALIGN_LSB 0
308#define PPP_SRC_PACK_ALIGN_MSB (1<<18)
309
310#define PPP_SRC_PLANE_INTERLVD 0
311#define PPP_SRC_PLANE_PSEUDOPLNR (1<<20)
312
313#define PPP_SRC_WMV9_MODE (1<<21)
314
315/* MDP_PPP_OPERATION_CONFIG / MDP_FULL_BYPASS_WORD14 */
316#define PPP_OP_SCALE_X_ON (1<<0)
317#define PPP_OP_SCALE_Y_ON (1<<1)
318
319#define PPP_OP_CONVERT_RGB2YCBCR 0
320#define PPP_OP_CONVERT_YCBCR2RGB (1<<2)
321#define PPP_OP_CONVERT_ON (1<<3)
322
323#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
324#define PPP_OP_CONVERT_MATRIX_SECONDARY (1<<4)
325
326#define PPP_OP_LUT_C0_ON (1<<5)
327#define PPP_OP_LUT_C1_ON (1<<6)
328#define PPP_OP_LUT_C2_ON (1<<7)
329
330/* rotate or blend enable */
331#define PPP_OP_ROT_ON (1<<8)
332
333#define PPP_OP_ROT_90 (1<<9)
334#define PPP_OP_FLIP_LR (1<<10)
335#define PPP_OP_FLIP_UD (1<<11)
336
337#define PPP_OP_BLEND_ON (1<<12)
338
339#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
340#define PPP_OP_BLEND_DSTPIXEL_ALPHA (1<<13)
341#define PPP_OP_BLEND_CONSTANT_ALPHA (1<<14)
342#define PPP_OP_BLEND_SRCPIXEL_TRANSP ((1<<13)|(1<<14))
343
344#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
345#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE (1<<15)
346
347#define PPP_OP_DITHER_EN (1<<16)
348
349#define PPP_OP_COLOR_SPACE_RGB 0
350#define PPP_OP_COLOR_SPACE_YCBCR (1<<17)
351
352#define PPP_OP_SRC_CHROMA_RGB 0
353#define PPP_OP_SRC_CHROMA_H2V1 (1<<18)
354#define PPP_OP_SRC_CHROMA_H1V2 (1<<19)
355#define PPP_OP_SRC_CHROMA_420 ((1<<18)|(1<<19))
356#define PPP_OP_SRC_CHROMA_COSITE 0
357#define PPP_OP_SRC_CHROMA_OFFSITE (1<<20)
358
359#define PPP_OP_DST_CHROMA_RGB 0
360#define PPP_OP_DST_CHROMA_H2V1 (1<<21)
361#define PPP_OP_DST_CHROMA_H1V2 (1<<22)
362#define PPP_OP_DST_CHROMA_420 ((1<<21)|(1<<22))
363#define PPP_OP_DST_CHROMA_COSITE 0
364#define PPP_OP_DST_CHROMA_OFFSITE (1<<23)
365
366#define PPP_BLEND_ALPHA_TRANSP (1<<24)
367
368#define PPP_OP_BG_CHROMA_RGB 0
369#define PPP_OP_BG_CHROMA_H2V1 (1<<25)
370#define PPP_OP_BG_CHROMA_H1V2 (1<<26)
371#define PPP_OP_BG_CHROMA_420 ((1<<25)|(1<<26))
372#define PPP_OP_BG_CHROMA_SITE_COSITE 0
373#define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27)
374
375/* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */
376#define PPP_DST_C0G_8BIT ((1<<0)|(1<<1))
377#define PPP_DST_C1B_8BIT ((1<<3)|(1<<2))
378#define PPP_DST_C2R_8BIT ((1<<5)|(1<<4))
379#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
380
381#define PPP_DST_C0G_6BIT (1<<1)
382#define PPP_DST_C1B_6BIT (1<<3)
383#define PPP_DST_C2R_6BIT (1<<5)
384
385#define PPP_DST_C0G_5BIT (1<<0)
386#define PPP_DST_C1B_5BIT (1<<2)
387#define PPP_DST_C2R_5BIT (1<<4)
388
389#define PPP_DST_C3A_8BIT ((1<<7)|(1<<6))
390#define PPP_DST_C3ALPHA_EN (1<<8)
391
392#define PPP_DST_INTERLVD_2COMPONENTS (1<<9)
393#define PPP_DST_INTERLVD_3COMPONENTS (1<<10)
394#define PPP_DST_INTERLVD_4COMPONENTS ((1<<10)|(1<<9))
395#define PPP_DST_INTERLVD_6COMPONENTS ((1<<11)|(1<<9))
396
397#define PPP_DST_PACK_LOOSE 0
398#define PPP_DST_PACK_TIGHT (1<<13)
399#define PPP_DST_PACK_ALIGN_LSB 0
400#define PPP_DST_PACK_ALIGN_MSB (1<<14)
401
402#define PPP_DST_OUT_SEL_AXI 0
403#define PPP_DST_OUT_SEL_MDDI (1<<15)
404
405#define PPP_DST_BPP_2BYTES (1<<16)
406#define PPP_DST_BPP_3BYTES (1<<17)
407#define PPP_DST_BPP_4BYTES ((1<<17)|(1<<16))
408
409#define PPP_DST_PLANE_INTERLVD 0
410#define PPP_DST_PLANE_PLANAR (1<<18)
411#define PPP_DST_PLANE_PSEUDOPLNR (1<<19)
412
413#define PPP_DST_TO_TV (1<<20)
414
415#define PPP_DST_MDDI_PRIMARY 0
416#define PPP_DST_MDDI_SECONDARY (1<<21)
417#define PPP_DST_MDDI_EXTERNAL (1<<22)
418
419/* image configurations by image type */
420#define PPP_CFG_MDP_RGB_565(dir) (PPP_##dir##_C2R_5BIT | \
421 PPP_##dir##_C0G_6BIT | \
422 PPP_##dir##_C1B_5BIT | \
423 PPP_##dir##_BPP_2BYTES | \
424 PPP_##dir##_INTERLVD_3COMPONENTS | \
425 PPP_##dir##_PACK_TIGHT | \
426 PPP_##dir##_PACK_ALIGN_LSB | \
427 PPP_##dir##_PLANE_INTERLVD)
428
429#define PPP_CFG_MDP_RGB_888(dir) (PPP_##dir##_C2R_8BIT | \
430 PPP_##dir##_C0G_8BIT | \
431 PPP_##dir##_C1B_8BIT | \
432 PPP_##dir##_BPP_3BYTES | \
433 PPP_##dir##_INTERLVD_3COMPONENTS | \
434 PPP_##dir##_PACK_TIGHT | \
435 PPP_##dir##_PACK_ALIGN_LSB | \
436 PPP_##dir##_PLANE_INTERLVD)
437
438#define PPP_CFG_MDP_ARGB_8888(dir) (PPP_##dir##_C2R_8BIT | \
439 PPP_##dir##_C0G_8BIT | \
440 PPP_##dir##_C1B_8BIT | \
441 PPP_##dir##_C3A_8BIT | \
442 PPP_##dir##_C3ALPHA_EN | \
443 PPP_##dir##_BPP_4BYTES | \
444 PPP_##dir##_INTERLVD_4COMPONENTS | \
445 PPP_##dir##_PACK_TIGHT | \
446 PPP_##dir##_PACK_ALIGN_LSB | \
447 PPP_##dir##_PLANE_INTERLVD)
448
449#define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
450#define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
451#define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
452
453#define PPP_CFG_MDP_Y_CBCR_H2V2(dir) (PPP_##dir##_C2R_8BIT | \
454 PPP_##dir##_C0G_8BIT | \
455 PPP_##dir##_C1B_8BIT | \
456 PPP_##dir##_C3A_8BIT | \
457 PPP_##dir##_BPP_2BYTES | \
458 PPP_##dir##_INTERLVD_2COMPONENTS | \
459 PPP_##dir##_PACK_TIGHT | \
460 PPP_##dir##_PACK_ALIGN_LSB | \
461 PPP_##dir##_PLANE_PSEUDOPLNR)
462
463#define PPP_CFG_MDP_Y_CRCB_H2V2(dir) PPP_CFG_MDP_Y_CBCR_H2V2(dir)
464
465#define PPP_CFG_MDP_YCRYCB_H2V1(dir) (PPP_##dir##_C2R_8BIT | \
466 PPP_##dir##_C0G_8BIT | \
467 PPP_##dir##_C1B_8BIT | \
468 PPP_##dir##_C3A_8BIT | \
469 PPP_##dir##_BPP_2BYTES | \
470 PPP_##dir##_INTERLVD_4COMPONENTS | \
471 PPP_##dir##_PACK_TIGHT | \
472 PPP_##dir##_PACK_ALIGN_LSB |\
473 PPP_##dir##_PLANE_INTERLVD)
474
475#define PPP_CFG_MDP_Y_CBCR_H2V1(dir) (PPP_##dir##_C2R_8BIT | \
476 PPP_##dir##_C0G_8BIT | \
477 PPP_##dir##_C1B_8BIT | \
478 PPP_##dir##_C3A_8BIT | \
479 PPP_##dir##_BPP_2BYTES | \
480 PPP_##dir##_INTERLVD_2COMPONENTS | \
481 PPP_##dir##_PACK_TIGHT | \
482 PPP_##dir##_PACK_ALIGN_LSB | \
483 PPP_##dir##_PLANE_PSEUDOPLNR)
484
485#define PPP_CFG_MDP_Y_CRCB_H2V1(dir) PPP_CFG_MDP_Y_CBCR_H2V1(dir)
486
487#define PPP_PACK_PATTERN_MDP_RGB_565 \
488 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8)
489#define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565
490#define PPP_PACK_PATTERN_MDP_XRGB_8888 \
491 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
492#define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888
493#define PPP_PACK_PATTERN_MDP_RGBA_8888 \
494 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
495#define PPP_PACK_PATTERN_MDP_BGRA_8888 \
496 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
497#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \
498 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8)
499#define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1
500#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1 \
501 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8)
502#define PPP_PACK_PATTERN_MDP_Y_CRCB_H2V2 PPP_PACK_PATTERN_MDP_Y_CRCB_H2V1
503#define PPP_PACK_PATTERN_MDP_YCRYCB_H2V1 \
504 MDP_GET_PACK_PATTERN(CLR_Y, CLR_R, CLR_Y, CLR_B, 8)
505
506#define PPP_CHROMA_SAMP_MDP_RGB_565(dir) PPP_OP_##dir##_CHROMA_RGB
507#define PPP_CHROMA_SAMP_MDP_RGB_888(dir) PPP_OP_##dir##_CHROMA_RGB
508#define PPP_CHROMA_SAMP_MDP_XRGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
509#define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
510#define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
511#define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
512#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
513#define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420
514#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
515#define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V2(dir) PPP_OP_##dir##_CHROMA_420
516#define PPP_CHROMA_SAMP_MDP_YCRYCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
517
518/* Helpful array generation macros */
519#define PPP_ARRAY0(name) \
520 [MDP_RGB_565] = PPP_##name##_MDP_RGB_565,\
521 [MDP_RGB_888] = PPP_##name##_MDP_RGB_888,\
522 [MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888,\
523 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\
524 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\
525 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\
526 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\
527 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\
528 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\
529 [MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2,\
530 [MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1
531
532#define PPP_ARRAY1(name, dir) \
533 [MDP_RGB_565] = PPP_##name##_MDP_RGB_565(dir),\
534 [MDP_RGB_888] = PPP_##name##_MDP_RGB_888(dir),\
535 [MDP_XRGB_8888] = PPP_##name##_MDP_XRGB_8888(dir),\
536 [MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\
537 [MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\
538 [MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\
539 [MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\
540 [MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\
541 [MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\
542 [MDP_Y_CRCB_H2V2] = PPP_##name##_MDP_Y_CRCB_H2V2(dir),\
543 [MDP_YCRYCB_H2V1] = PPP_##name##_MDP_YCRYCB_H2V1(dir)
544
545#define IS_YCRCB(img) ((img == MDP_Y_CRCB_H2V2) | (img == MDP_Y_CBCR_H2V2) | \
546 (img == MDP_Y_CRCB_H2V1) | (img == MDP_Y_CBCR_H2V1) | \
547 (img == MDP_YCRYCB_H2V1))
548#define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \
549 (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
550 (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888))
551#define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
552 (img == MDP_BGRA_8888))
553
554#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
555 (img == MDP_Y_CBCR_H2V2) | \
556 (img == MDP_Y_CRCB_H2V1) | \
557 (img == MDP_Y_CBCR_H2V1))
558
559/* Mappings from addr to purpose */
560#define PPP_ADDR_SRC_ROI MDP_FULL_BYPASS_WORD2
561#define PPP_ADDR_SRC0 MDP_FULL_BYPASS_WORD3
562#define PPP_ADDR_SRC1 MDP_FULL_BYPASS_WORD4
563#define PPP_ADDR_SRC_YSTRIDE MDP_FULL_BYPASS_WORD7
564#define PPP_ADDR_SRC_CFG MDP_FULL_BYPASS_WORD9
565#define PPP_ADDR_SRC_PACK_PATTERN MDP_FULL_BYPASS_WORD10
566#define PPP_ADDR_OPERATION MDP_FULL_BYPASS_WORD14
567#define PPP_ADDR_PHASEX_INIT MDP_FULL_BYPASS_WORD15
568#define PPP_ADDR_PHASEY_INIT MDP_FULL_BYPASS_WORD16
569#define PPP_ADDR_PHASEX_STEP MDP_FULL_BYPASS_WORD17
570#define PPP_ADDR_PHASEY_STEP MDP_FULL_BYPASS_WORD18
571#define PPP_ADDR_ALPHA_TRANSP MDP_FULL_BYPASS_WORD19
572#define PPP_ADDR_DST_CFG MDP_FULL_BYPASS_WORD20
573#define PPP_ADDR_DST_PACK_PATTERN MDP_FULL_BYPASS_WORD21
574#define PPP_ADDR_DST_ROI MDP_FULL_BYPASS_WORD25
575#define PPP_ADDR_DST0 MDP_FULL_BYPASS_WORD26
576#define PPP_ADDR_DST1 MDP_FULL_BYPASS_WORD27
577#define PPP_ADDR_DST_YSTRIDE MDP_FULL_BYPASS_WORD30
578#define PPP_ADDR_EDGE MDP_FULL_BYPASS_WORD46
579#define PPP_ADDR_BG0 MDP_FULL_BYPASS_WORD48
580#define PPP_ADDR_BG1 MDP_FULL_BYPASS_WORD49
581#define PPP_ADDR_BG_YSTRIDE MDP_FULL_BYPASS_WORD51
582#define PPP_ADDR_BG_CFG MDP_FULL_BYPASS_WORD53
583#define PPP_ADDR_BG_PACK_PATTERN MDP_FULL_BYPASS_WORD54
584
585/* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
586#define DMA_DSTC0G_6BITS (1<<1)
587#define DMA_DSTC1B_6BITS (1<<3)
588#define DMA_DSTC2R_6BITS (1<<5)
589#define DMA_DSTC0G_5BITS (1<<0)
590#define DMA_DSTC1B_5BITS (1<<2)
591#define DMA_DSTC2R_5BITS (1<<4)
592
593#define DMA_PACK_TIGHT (1<<6)
594#define DMA_PACK_LOOSE 0
595#define DMA_PACK_ALIGN_LSB 0
596#define DMA_PACK_ALIGN_MSB (1<<7)
597#define DMA_PACK_PATTERN_RGB \
598 (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
599
600#define DMA_OUT_SEL_AHB 0
601#define DMA_OUT_SEL_MDDI (1<<14)
602#define DMA_AHBM_LCD_SEL_PRIMARY 0
603#define DMA_AHBM_LCD_SEL_SECONDARY (1<<15)
604#define DMA_IBUF_C3ALPHA_EN (1<<16)
605#define DMA_DITHER_EN (1<<17)
606
607#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
608#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18)
609#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19)
610
611#define DMA_IBUF_FORMAT_RGB565 (1<<20)
612#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
613
614#define DMA_IBUF_NONCONTIGUOUS (1<<21)
615
616/* MDDI REGISTER ? */
617#define MDDI_VDO_PACKET_DESC 0x5666
618#define MDDI_VDO_PACKET_PRIM 0xC3
619#define MDDI_VDO_PACKET_SECD 0xC0
620
621#endif
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
new file mode 100644
index 000000000000..4ff001f4cbbd
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp.c
@@ -0,0 +1,730 @@
1/* drivers/video/msm/mdp_ppp.c
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#include <linux/fb.h>
16#include <linux/file.h>
17#include <linux/delay.h>
18#include <linux/msm_mdp.h>
19#include <mach/msm_fb.h>
20
21#include "mdp_hw.h"
22#include "mdp_scale_tables.h"
23
24#define DLOG(x...) do {} while (0)
25
26#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
27static int downscale_y_table = MDP_DOWNSCALE_MAX;
28static int downscale_x_table = MDP_DOWNSCALE_MAX;
29
30struct mdp_regs {
31 uint32_t src0;
32 uint32_t src1;
33 uint32_t dst0;
34 uint32_t dst1;
35 uint32_t src_cfg;
36 uint32_t dst_cfg;
37 uint32_t src_pack;
38 uint32_t dst_pack;
39 uint32_t src_rect;
40 uint32_t dst_rect;
41 uint32_t src_ystride;
42 uint32_t dst_ystride;
43 uint32_t op;
44 uint32_t src_bpp;
45 uint32_t dst_bpp;
46 uint32_t edge;
47 uint32_t phasex_init;
48 uint32_t phasey_init;
49 uint32_t phasex_step;
50 uint32_t phasey_step;
51};
52
53static uint32_t pack_pattern[] = {
54 PPP_ARRAY0(PACK_PATTERN)
55};
56
57static uint32_t src_img_cfg[] = {
58 PPP_ARRAY1(CFG, SRC)
59};
60
61static uint32_t dst_img_cfg[] = {
62 PPP_ARRAY1(CFG, DST)
63};
64
65static uint32_t bytes_per_pixel[] = {
66 [MDP_RGB_565] = 2,
67 [MDP_RGB_888] = 3,
68 [MDP_XRGB_8888] = 4,
69 [MDP_ARGB_8888] = 4,
70 [MDP_RGBA_8888] = 4,
71 [MDP_BGRA_8888] = 4,
72 [MDP_Y_CBCR_H2V1] = 1,
73 [MDP_Y_CBCR_H2V2] = 1,
74 [MDP_Y_CRCB_H2V1] = 1,
75 [MDP_Y_CRCB_H2V2] = 1,
76 [MDP_YCRYCB_H2V1] = 2
77};
78
79static uint32_t dst_op_chroma[] = {
80 PPP_ARRAY1(CHROMA_SAMP, DST)
81};
82
83static uint32_t src_op_chroma[] = {
84 PPP_ARRAY1(CHROMA_SAMP, SRC)
85};
86
87static uint32_t bg_op_chroma[] = {
88 PPP_ARRAY1(CHROMA_SAMP, BG)
89};
90
91static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
92{
93 regs->dst0 += (req->dst_rect.w -
94 min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
95 regs->dst1 += (req->dst_rect.w -
96 min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
97}
98
99static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
100{
101 regs->dst0 += (req->dst_rect.h -
102 min((uint32_t)16, req->dst_rect.h)) *
103 regs->dst_ystride;
104 regs->dst1 += (req->dst_rect.h -
105 min((uint32_t)16, req->dst_rect.h)) *
106 regs->dst_ystride;
107}
108
109static void blit_rotate(struct mdp_blit_req *req,
110 struct mdp_regs *regs)
111{
112 if (req->flags == MDP_ROT_NOP)
113 return;
114
115 regs->op |= PPP_OP_ROT_ON;
116 if ((req->flags & MDP_ROT_90 || req->flags & MDP_FLIP_LR) &&
117 !(req->flags & MDP_ROT_90 && req->flags & MDP_FLIP_LR))
118 rotate_dst_addr_x(req, regs);
119 if (req->flags & MDP_ROT_90)
120 regs->op |= PPP_OP_ROT_90;
121 if (req->flags & MDP_FLIP_UD) {
122 regs->op |= PPP_OP_FLIP_UD;
123 rotate_dst_addr_y(req, regs);
124 }
125 if (req->flags & MDP_FLIP_LR)
126 regs->op |= PPP_OP_FLIP_LR;
127}
128
129static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs)
130{
131 if (req->src.format == req->dst.format)
132 return;
133 if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) {
134 regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON;
135 } else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) {
136 regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON;
137 if (req->dst.format == MDP_RGB_565)
138 regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
139 }
140}
141
142#define GET_BIT_RANGE(value, high, low) \
143 (((1 << (high - low + 1)) - 1) & (value >> low))
144static uint32_t transp_convert(struct mdp_blit_req *req)
145{
146 uint32_t transp = 0;
147 if (req->src.format == MDP_RGB_565) {
148 /* pad each value to 8 bits by copying the high bits into the
149 * low end, convert RGB to RBG by switching low 2 components */
150 transp |= ((GET_BIT_RANGE(req->transp_mask, 15, 11) << 3) |
151 (GET_BIT_RANGE(req->transp_mask, 15, 13))) << 16;
152
153 transp |= ((GET_BIT_RANGE(req->transp_mask, 4, 0) << 3) |
154 (GET_BIT_RANGE(req->transp_mask, 4, 2))) << 8;
155
156 transp |= (GET_BIT_RANGE(req->transp_mask, 10, 5) << 2) |
157 (GET_BIT_RANGE(req->transp_mask, 10, 9));
158 } else {
159 /* convert RGB to RBG */
160 transp |= (GET_BIT_RANGE(req->transp_mask, 15, 8)) |
161 (GET_BIT_RANGE(req->transp_mask, 23, 16) << 16) |
162 (GET_BIT_RANGE(req->transp_mask, 7, 0) << 8);
163 }
164 return transp;
165}
166#undef GET_BIT_RANGE
167
168static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs)
169{
170 /* TRANSP BLEND */
171 if (req->transp_mask != MDP_TRANSP_NOP) {
172 req->transp_mask = transp_convert(req);
173 if (req->alpha != MDP_ALPHA_NOP) {
174 /* use blended transparancy mode
175 * pixel = (src == transp) ? dst : blend
176 * blend is combo of blend_eq_sel and
177 * blend_alpha_sel */
178 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
179 PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
180 PPP_OP_BLEND_CONSTANT_ALPHA |
181 PPP_BLEND_ALPHA_TRANSP;
182 } else {
183 /* simple transparancy mode
184 * pixel = (src == transp) ? dst : src */
185 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
186 PPP_OP_BLEND_SRCPIXEL_TRANSP;
187 }
188 }
189
190 req->alpha &= 0xff;
191 /* ALPHA BLEND */
192 if (HAS_ALPHA(req->src.format)) {
193 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
194 PPP_OP_BLEND_SRCPIXEL_ALPHA;
195 } else if (req->alpha < MDP_ALPHA_NOP) {
196 /* just blend by alpha */
197 regs->op |= PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
198 PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
199 PPP_OP_BLEND_CONSTANT_ALPHA;
200 }
201
202 regs->op |= bg_op_chroma[req->dst.format];
203}
204
205#define ONE_HALF (1LL << 32)
206#define ONE (1LL << 33)
207#define TWO (2LL << 33)
208#define THREE (3LL << 33)
209#define FRAC_MASK (ONE - 1)
210#define INT_MASK (~FRAC_MASK)
211
212static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
213 uint32_t *phase_init, uint32_t *phase_step)
214{
215 /* to improve precicsion calculations are done in U31.33 and converted
216 * to U3.29 at the end */
217 int64_t k1, k2, k3, k4, tmp;
218 uint64_t n, d, os, os_p, od, od_p, oreq;
219 unsigned rpa = 0;
220 int64_t ip64, delta;
221
222 if (dim_out % 3 == 0)
223 rpa = !(dim_in % (dim_out / 3));
224
225 n = ((uint64_t)dim_out) << 34;
226 d = dim_in;
227 if (!d)
228 return -1;
229 do_div(n, d);
230 k3 = (n + 1) >> 1;
231 if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
232 DLOG("crap bad scale\n");
233 return -1;
234 }
235 n = ((uint64_t)dim_in) << 34;
236 d = (uint64_t)dim_out;
237 if (!d)
238 return -1;
239 do_div(n, d);
240 k1 = (n + 1) >> 1;
241 k2 = (k1 - ONE) >> 1;
242
243 *phase_init = (int)(k2 >> 4);
244 k4 = (k3 - ONE) >> 1;
245
246 if (rpa) {
247 os = ((uint64_t)origin << 33) - ONE_HALF;
248 tmp = (dim_out * os) + ONE_HALF;
249 if (!dim_in)
250 return -1;
251 do_div(tmp, dim_in);
252 od = tmp - ONE_HALF;
253 } else {
254 os = ((uint64_t)origin << 1) - 1;
255 od = (((k3 * os) >> 1) + k4);
256 }
257
258 od_p = od & INT_MASK;
259 if (od_p != od)
260 od_p += ONE;
261
262 if (rpa) {
263 tmp = (dim_in * od_p) + ONE_HALF;
264 if (!dim_in)
265 return -1;
266 do_div(tmp, dim_in);
267 os_p = tmp - ONE_HALF;
268 } else {
269 os_p = ((k1 * (od_p >> 33)) + k2);
270 }
271
272 oreq = (os_p & INT_MASK) - ONE;
273
274 ip64 = os_p - oreq;
275 delta = ((int64_t)(origin) << 33) - oreq;
276 ip64 -= delta;
277 /* limit to valid range before the left shift */
278 delta = (ip64 & (1LL << 63)) ? 4 : -4;
279 delta <<= 33;
280 while (abs((int)(ip64 >> 33)) > 4)
281 ip64 += delta;
282 *phase_init = (int)(ip64 >> 4);
283 *phase_step = (uint32_t)(k1 >> 4);
284 return 0;
285}
286
287static void load_scale_table(const struct mdp_info *mdp,
288 struct mdp_table_entry *table, int len)
289{
290 int i;
291 for (i = 0; i < len; i++)
292 mdp_writel(mdp, table[i].val, table[i].reg);
293}
294
295enum {
296IMG_LEFT,
297IMG_RIGHT,
298IMG_TOP,
299IMG_BOTTOM,
300};
301
302static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
303 uint32_t *interp1, uint32_t *interp2,
304 uint32_t *repeat1, uint32_t *repeat2) {
305 if (src > 3 * dst) {
306 *interp1 = 0;
307 *interp2 = src - 1;
308 *repeat1 = 0;
309 *repeat2 = 0;
310 } else if (src == 3 * dst) {
311 *interp1 = 0;
312 *interp2 = src;
313 *repeat1 = 0;
314 *repeat2 = 1;
315 } else if (src > dst && src < 3 * dst) {
316 *interp1 = -1;
317 *interp2 = src;
318 *repeat1 = 1;
319 *repeat2 = 1;
320 } else if (src == dst) {
321 *interp1 = -1;
322 *interp2 = src + 1;
323 *repeat1 = 1;
324 *repeat2 = 2;
325 } else {
326 *interp1 = -2;
327 *interp2 = src + 1;
328 *repeat1 = 2;
329 *repeat2 = 2;
330 }
331 *interp1 += src_coord;
332 *interp2 += src_coord;
333}
334
335static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
336{
337 int32_t luma_interp[4];
338 int32_t luma_repeat[4];
339 int32_t chroma_interp[4];
340 int32_t chroma_bound[4];
341 int32_t chroma_repeat[4];
342 uint32_t dst_w, dst_h;
343
344 memset(&luma_interp, 0, sizeof(int32_t) * 4);
345 memset(&luma_repeat, 0, sizeof(int32_t) * 4);
346 memset(&chroma_interp, 0, sizeof(int32_t) * 4);
347 memset(&chroma_bound, 0, sizeof(int32_t) * 4);
348 memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
349 regs->edge = 0;
350
351 if (req->flags & MDP_ROT_90) {
352 dst_w = req->dst_rect.h;
353 dst_h = req->dst_rect.w;
354 } else {
355 dst_w = req->dst_rect.w;
356 dst_h = req->dst_rect.h;
357 }
358
359 if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
360 get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
361 &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
362 &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
363 get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
364 &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
365 &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
366 } else {
367 luma_interp[IMG_LEFT] = req->src_rect.x;
368 luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
369 luma_interp[IMG_TOP] = req->src_rect.y;
370 luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
371 luma_repeat[IMG_LEFT] = 0;
372 luma_repeat[IMG_TOP] = 0;
373 luma_repeat[IMG_RIGHT] = 0;
374 luma_repeat[IMG_BOTTOM] = 0;
375 }
376
377 chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
378 chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
379 chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
380 chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
381
382 chroma_bound[IMG_LEFT] = req->src_rect.x;
383 chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
384 chroma_bound[IMG_TOP] = req->src_rect.y;
385 chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
386
387 if (IS_YCRCB(req->src.format)) {
388 chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
389 chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
390
391 chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
392 chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
393 }
394
395 if (req->src.format == MDP_Y_CBCR_H2V2 ||
396 req->src.format == MDP_Y_CRCB_H2V2) {
397 chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
398 chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
399 >> 1;
400 chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
401 chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
402 }
403
404 chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
405 chroma_interp[IMG_LEFT];
406 chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
407 chroma_bound[IMG_RIGHT];
408 chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
409 chroma_interp[IMG_TOP];
410 chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
411 chroma_bound[IMG_BOTTOM];
412
413 if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
414 chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
415 chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
416 chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
417 luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
418 luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
419 luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
420 luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
421 return -1;
422
423 regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
424 regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
425 regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
426 regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
427 regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
428 regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
429 regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
430 regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
431 return 0;
432}
433
434static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
435 struct mdp_regs *regs)
436{
437 uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
438 uint32_t scale_factor_x, scale_factor_y;
439 uint32_t downscale;
440 uint32_t dst_w, dst_h;
441
442 if (req->flags & MDP_ROT_90) {
443 dst_w = req->dst_rect.h;
444 dst_h = req->dst_rect.w;
445 } else {
446 dst_w = req->dst_rect.w;
447 dst_h = req->dst_rect.h;
448 }
449 if ((req->src_rect.w == dst_w) && (req->src_rect.h == dst_h) &&
450 !(req->flags & MDP_BLUR)) {
451 regs->phasex_init = 0;
452 regs->phasey_init = 0;
453 regs->phasex_step = 0;
454 regs->phasey_step = 0;
455 return 0;
456 }
457
458 if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
459 &phase_step_x) ||
460 scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
461 &phase_step_y))
462 return -1;
463
464 scale_factor_x = (dst_w * 10) / req->src_rect.w;
465 scale_factor_y = (dst_h * 10) / req->src_rect.h;
466
467 if (scale_factor_x > 8)
468 downscale = MDP_DOWNSCALE_PT8TO1;
469 else if (scale_factor_x > 6)
470 downscale = MDP_DOWNSCALE_PT6TOPT8;
471 else if (scale_factor_x > 4)
472 downscale = MDP_DOWNSCALE_PT4TOPT6;
473 else
474 downscale = MDP_DOWNSCALE_PT2TOPT4;
475 if (downscale != downscale_x_table) {
476 load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
477 downscale_x_table = downscale;
478 }
479
480 if (scale_factor_y > 8)
481 downscale = MDP_DOWNSCALE_PT8TO1;
482 else if (scale_factor_y > 6)
483 downscale = MDP_DOWNSCALE_PT6TOPT8;
484 else if (scale_factor_y > 4)
485 downscale = MDP_DOWNSCALE_PT4TOPT6;
486 else
487 downscale = MDP_DOWNSCALE_PT2TOPT4;
488 if (downscale != downscale_y_table) {
489 load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
490 downscale_y_table = downscale;
491 }
492
493 regs->phasex_init = phase_init_x;
494 regs->phasey_init = phase_init_y;
495 regs->phasex_step = phase_step_x;
496 regs->phasey_step = phase_step_y;
497 regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
498 return 0;
499
500}
501
502static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
503 struct mdp_regs *regs)
504{
505 if (!(req->flags & MDP_BLUR))
506 return;
507
508 if (!(downscale_x_table == MDP_DOWNSCALE_BLUR &&
509 downscale_y_table == MDP_DOWNSCALE_BLUR)) {
510 load_scale_table(mdp, mdp_gaussian_blur_table, 128);
511 downscale_x_table = MDP_DOWNSCALE_BLUR;
512 downscale_y_table = MDP_DOWNSCALE_BLUR;
513 }
514
515 regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
516}
517
518
519#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
520
521#define Y_TO_CRCB_RATIO(format) \
522 ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
523 (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
524
525static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
526 uint32_t *len0, uint32_t *len1)
527{
528 *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
529 if (IS_PSEUDOPLNR(img->format))
530 *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
531 else
532 *len1 = 0;
533}
534
535static int valid_src_dst(unsigned long src_start, unsigned long src_len,
536 unsigned long dst_start, unsigned long dst_len,
537 struct mdp_blit_req *req, struct mdp_regs *regs)
538{
539 unsigned long src_min_ok = src_start;
540 unsigned long src_max_ok = src_start + src_len;
541 unsigned long dst_min_ok = dst_start;
542 unsigned long dst_max_ok = dst_start + dst_len;
543 uint32_t src0_len, src1_len, dst0_len, dst1_len;
544 get_len(&req->src, &req->src_rect, regs->src_bpp, &src0_len,
545 &src1_len);
546 get_len(&req->dst, &req->dst_rect, regs->dst_bpp, &dst0_len,
547 &dst1_len);
548
549 if (regs->src0 < src_min_ok || regs->src0 > src_max_ok ||
550 regs->src0 + src0_len > src_max_ok) {
551 DLOG("invalid_src %x %x %lx %lx\n", regs->src0,
552 src0_len, src_min_ok, src_max_ok);
553 return 0;
554 }
555 if (regs->src_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
556 if (regs->src1 < src_min_ok || regs->src1 > src_max_ok ||
557 regs->src1 + src1_len > src_max_ok) {
558 DLOG("invalid_src1");
559 return 0;
560 }
561 }
562 if (regs->dst0 < dst_min_ok || regs->dst0 > dst_max_ok ||
563 regs->dst0 + dst0_len > dst_max_ok) {
564 DLOG("invalid_dst");
565 return 0;
566 }
567 if (regs->dst_cfg & PPP_SRC_PLANE_PSEUDOPLNR) {
568 if (regs->dst1 < dst_min_ok || regs->dst1 > dst_max_ok ||
569 regs->dst1 + dst1_len > dst_max_ok) {
570 DLOG("invalid_dst1");
571 return 0;
572 }
573 }
574 return 1;
575}
576
577
578static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs,
579 struct file *src_file, struct file *dst_file)
580{
581}
582
583static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
584 uint32_t base, uint32_t bpp, uint32_t cfg,
585 uint32_t *addr, uint32_t *ystride)
586{
587 uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
588 uint32_t compress_h = 2;
589 uint32_t offset;
590
591 if (IS_PSEUDOPLNR(img->format)) {
592 offset = (rect->x / compress_h) * compress_h;
593 offset += rect->y == 0 ? 0 :
594 ((rect->y + 1) / compress_v) * img->width;
595 *addr = base + (img->width * img->height * bpp);
596 *addr += offset * bpp;
597 *ystride |= *ystride << 16;
598 } else {
599 *addr = 0;
600 }
601}
602
603static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
604 struct mdp_regs *regs, struct file *src_file,
605 struct file *dst_file)
606{
607 mdp_writel(mdp, 1, 0x060);
608 mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
609 mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0);
610 mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1);
611 mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
612 mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
613 mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
614
615 mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION);
616 mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
617 mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
618 mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
619 mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
620
621 mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
622 PPP_ADDR_ALPHA_TRANSP);
623
624 mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
625 mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
626 mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
627 mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0);
628 mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1);
629 mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
630
631 mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE);
632 if (regs->op & PPP_OP_BLEND_ON) {
633 mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0);
634 mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1);
635 mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE);
636 mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG);
637 mdp_writel(mdp, pack_pattern[req->dst.format],
638 PPP_ADDR_BG_PACK_PATTERN);
639 }
640 flush_imgs(req, regs, src_file, dst_file);
641 mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START);
642 return 0;
643}
644
645int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
646 struct file *src_file, unsigned long src_start, unsigned long src_len,
647 struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
648{
649 struct mdp_regs regs = {0};
650
651 if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
652 req->dst.format >= MDP_IMGTYPE_LIMIT)) {
653 printk(KERN_ERR "mpd_ppp: img is of wrong format\n");
654 return -EINVAL;
655 }
656
657 if (unlikely(req->src_rect.x > req->src.width ||
658 req->src_rect.y > req->src.height ||
659 req->dst_rect.x > req->dst.width ||
660 req->dst_rect.y > req->dst.height)) {
661 printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n");
662 return -EINVAL;
663 }
664
665 /* set the src image configuration */
666 regs.src_cfg = src_img_cfg[req->src.format];
667 regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
668 regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
669 regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
670 regs.src_pack = pack_pattern[req->src.format];
671
672 /* set the dest image configuration */
673 regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
674 regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
675 regs.dst_pack = pack_pattern[req->dst.format];
676
677 /* set src, bpp, start pixel and ystride */
678 regs.src_bpp = bytes_per_pixel[req->src.format];
679 regs.src0 = src_start + req->src.offset;
680 regs.src_ystride = req->src.width * regs.src_bpp;
681 get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
682 regs.src_cfg, &regs.src1, &regs.src_ystride);
683 regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
684 regs.src_bpp;
685
686 /* set dst, bpp, start pixel and ystride */
687 regs.dst_bpp = bytes_per_pixel[req->dst.format];
688 regs.dst0 = dst_start + req->dst.offset;
689 regs.dst_ystride = req->dst.width * regs.dst_bpp;
690 get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
691 regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
692 regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
693 regs.dst_bpp;
694
695 if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
696 &regs)) {
697 printk(KERN_ERR "mpd_ppp: final src or dst location is "
698 "invalid, are you trying to make an image too large "
699 "or to place it outside the screen?\n");
700 return -EINVAL;
701 }
702
703 /* set up operation register */
704 regs.op = 0;
705 blit_rotate(req, &regs);
706 blit_convert(req, &regs);
707 if (req->flags & MDP_DITHER)
708 regs.op |= PPP_OP_DITHER_EN;
709 blit_blend(req, &regs);
710 if (blit_scale(mdp, req, &regs)) {
711 printk(KERN_ERR "mpd_ppp: error computing scale for img.\n");
712 return -EINVAL;
713 }
714 blit_blur(mdp, req, &regs);
715 regs.op |= dst_op_chroma[req->dst.format] |
716 src_op_chroma[req->src.format];
717
718 /* if the image is YCRYCB, the x and w must be even */
719 if (unlikely(req->src.format == MDP_YCRYCB_H2V1)) {
720 req->src_rect.x = req->src_rect.x & (~0x1);
721 req->src_rect.w = req->src_rect.w & (~0x1);
722 req->dst_rect.x = req->dst_rect.x & (~0x1);
723 req->dst_rect.w = req->dst_rect.w & (~0x1);
724 }
725 if (get_edge_cond(req, &regs))
726 return -EINVAL;
727
728 send_blit(mdp, req, &regs, src_file, dst_file);
729 return 0;
730}
diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/msm/mdp_scale_tables.c
new file mode 100644
index 000000000000..604783b2e17c
--- /dev/null
+++ b/drivers/video/msm/mdp_scale_tables.c
@@ -0,0 +1,766 @@
1/* drivers/video/msm_fb/mdp_scale_tables.c
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include "mdp_scale_tables.h"
17#include "mdp_hw.h"
18
19struct mdp_table_entry mdp_upscale_table[] = {
20 { 0x5fffc, 0x0 },
21 { 0x50200, 0x7fc00000 },
22 { 0x5fffc, 0xff80000d },
23 { 0x50204, 0x7ec003f9 },
24 { 0x5fffc, 0xfec0001c },
25 { 0x50208, 0x7d4003f3 },
26 { 0x5fffc, 0xfe40002b },
27 { 0x5020c, 0x7b8003ed },
28 { 0x5fffc, 0xfd80003c },
29 { 0x50210, 0x794003e8 },
30 { 0x5fffc, 0xfcc0004d },
31 { 0x50214, 0x76c003e4 },
32 { 0x5fffc, 0xfc40005f },
33 { 0x50218, 0x73c003e0 },
34 { 0x5fffc, 0xfb800071 },
35 { 0x5021c, 0x708003de },
36 { 0x5fffc, 0xfac00085 },
37 { 0x50220, 0x6d0003db },
38 { 0x5fffc, 0xfa000098 },
39 { 0x50224, 0x698003d9 },
40 { 0x5fffc, 0xf98000ac },
41 { 0x50228, 0x654003d8 },
42 { 0x5fffc, 0xf8c000c1 },
43 { 0x5022c, 0x610003d7 },
44 { 0x5fffc, 0xf84000d5 },
45 { 0x50230, 0x5c8003d7 },
46 { 0x5fffc, 0xf7c000e9 },
47 { 0x50234, 0x580003d7 },
48 { 0x5fffc, 0xf74000fd },
49 { 0x50238, 0x534003d8 },
50 { 0x5fffc, 0xf6c00112 },
51 { 0x5023c, 0x4e8003d8 },
52 { 0x5fffc, 0xf6800126 },
53 { 0x50240, 0x494003da },
54 { 0x5fffc, 0xf600013a },
55 { 0x50244, 0x448003db },
56 { 0x5fffc, 0xf600014d },
57 { 0x50248, 0x3f4003dd },
58 { 0x5fffc, 0xf5c00160 },
59 { 0x5024c, 0x3a4003df },
60 { 0x5fffc, 0xf5c00172 },
61 { 0x50250, 0x354003e1 },
62 { 0x5fffc, 0xf5c00184 },
63 { 0x50254, 0x304003e3 },
64 { 0x5fffc, 0xf6000195 },
65 { 0x50258, 0x2b0003e6 },
66 { 0x5fffc, 0xf64001a6 },
67 { 0x5025c, 0x260003e8 },
68 { 0x5fffc, 0xf6c001b4 },
69 { 0x50260, 0x214003eb },
70 { 0x5fffc, 0xf78001c2 },
71 { 0x50264, 0x1c4003ee },
72 { 0x5fffc, 0xf80001cf },
73 { 0x50268, 0x17c003f1 },
74 { 0x5fffc, 0xf90001db },
75 { 0x5026c, 0x134003f3 },
76 { 0x5fffc, 0xfa0001e5 },
77 { 0x50270, 0xf0003f6 },
78 { 0x5fffc, 0xfb4001ee },
79 { 0x50274, 0xac003f9 },
80 { 0x5fffc, 0xfcc001f5 },
81 { 0x50278, 0x70003fb },
82 { 0x5fffc, 0xfe4001fb },
83 { 0x5027c, 0x34003fe },
84};
85
86static struct mdp_table_entry mdp_downscale_x_table_PT2TOPT4[] = {
87 { 0x5fffc, 0x740008c },
88 { 0x50280, 0x33800088 },
89 { 0x5fffc, 0x800008e },
90 { 0x50284, 0x33400084 },
91 { 0x5fffc, 0x8400092 },
92 { 0x50288, 0x33000080 },
93 { 0x5fffc, 0x9000094 },
94 { 0x5028c, 0x3300007b },
95 { 0x5fffc, 0x9c00098 },
96 { 0x50290, 0x32400077 },
97 { 0x5fffc, 0xa40009b },
98 { 0x50294, 0x32000073 },
99 { 0x5fffc, 0xb00009d },
100 { 0x50298, 0x31c0006f },
101 { 0x5fffc, 0xbc000a0 },
102 { 0x5029c, 0x3140006b },
103 { 0x5fffc, 0xc8000a2 },
104 { 0x502a0, 0x31000067 },
105 { 0x5fffc, 0xd8000a5 },
106 { 0x502a4, 0x30800062 },
107 { 0x5fffc, 0xe4000a8 },
108 { 0x502a8, 0x2fc0005f },
109 { 0x5fffc, 0xec000aa },
110 { 0x502ac, 0x2fc0005b },
111 { 0x5fffc, 0xf8000ad },
112 { 0x502b0, 0x2f400057 },
113 { 0x5fffc, 0x108000b0 },
114 { 0x502b4, 0x2e400054 },
115 { 0x5fffc, 0x114000b2 },
116 { 0x502b8, 0x2e000050 },
117 { 0x5fffc, 0x124000b4 },
118 { 0x502bc, 0x2d80004c },
119 { 0x5fffc, 0x130000b6 },
120 { 0x502c0, 0x2d000049 },
121 { 0x5fffc, 0x140000b8 },
122 { 0x502c4, 0x2c800045 },
123 { 0x5fffc, 0x150000b9 },
124 { 0x502c8, 0x2c000042 },
125 { 0x5fffc, 0x15c000bd },
126 { 0x502cc, 0x2b40003e },
127 { 0x5fffc, 0x16c000bf },
128 { 0x502d0, 0x2a80003b },
129 { 0x5fffc, 0x17c000bf },
130 { 0x502d4, 0x2a000039 },
131 { 0x5fffc, 0x188000c2 },
132 { 0x502d8, 0x29400036 },
133 { 0x5fffc, 0x19c000c4 },
134 { 0x502dc, 0x28800032 },
135 { 0x5fffc, 0x1ac000c5 },
136 { 0x502e0, 0x2800002f },
137 { 0x5fffc, 0x1bc000c7 },
138 { 0x502e4, 0x2740002c },
139 { 0x5fffc, 0x1cc000c8 },
140 { 0x502e8, 0x26c00029 },
141 { 0x5fffc, 0x1dc000c9 },
142 { 0x502ec, 0x26000027 },
143 { 0x5fffc, 0x1ec000cc },
144 { 0x502f0, 0x25000024 },
145 { 0x5fffc, 0x200000cc },
146 { 0x502f4, 0x24800021 },
147 { 0x5fffc, 0x210000cd },
148 { 0x502f8, 0x23800020 },
149 { 0x5fffc, 0x220000ce },
150 { 0x502fc, 0x2300001d },
151};
152
153static struct mdp_table_entry mdp_downscale_x_table_PT4TOPT6[] = {
154 { 0x5fffc, 0x740008c },
155 { 0x50280, 0x33800088 },
156 { 0x5fffc, 0x800008e },
157 { 0x50284, 0x33400084 },
158 { 0x5fffc, 0x8400092 },
159 { 0x50288, 0x33000080 },
160 { 0x5fffc, 0x9000094 },
161 { 0x5028c, 0x3300007b },
162 { 0x5fffc, 0x9c00098 },
163 { 0x50290, 0x32400077 },
164 { 0x5fffc, 0xa40009b },
165 { 0x50294, 0x32000073 },
166 { 0x5fffc, 0xb00009d },
167 { 0x50298, 0x31c0006f },
168 { 0x5fffc, 0xbc000a0 },
169 { 0x5029c, 0x3140006b },
170 { 0x5fffc, 0xc8000a2 },
171 { 0x502a0, 0x31000067 },
172 { 0x5fffc, 0xd8000a5 },
173 { 0x502a4, 0x30800062 },
174 { 0x5fffc, 0xe4000a8 },
175 { 0x502a8, 0x2fc0005f },
176 { 0x5fffc, 0xec000aa },
177 { 0x502ac, 0x2fc0005b },
178 { 0x5fffc, 0xf8000ad },
179 { 0x502b0, 0x2f400057 },
180 { 0x5fffc, 0x108000b0 },
181 { 0x502b4, 0x2e400054 },
182 { 0x5fffc, 0x114000b2 },
183 { 0x502b8, 0x2e000050 },
184 { 0x5fffc, 0x124000b4 },
185 { 0x502bc, 0x2d80004c },
186 { 0x5fffc, 0x130000b6 },
187 { 0x502c0, 0x2d000049 },
188 { 0x5fffc, 0x140000b8 },
189 { 0x502c4, 0x2c800045 },
190 { 0x5fffc, 0x150000b9 },
191 { 0x502c8, 0x2c000042 },
192 { 0x5fffc, 0x15c000bd },
193 { 0x502cc, 0x2b40003e },
194 { 0x5fffc, 0x16c000bf },
195 { 0x502d0, 0x2a80003b },
196 { 0x5fffc, 0x17c000bf },
197 { 0x502d4, 0x2a000039 },
198 { 0x5fffc, 0x188000c2 },
199 { 0x502d8, 0x29400036 },
200 { 0x5fffc, 0x19c000c4 },
201 { 0x502dc, 0x28800032 },
202 { 0x5fffc, 0x1ac000c5 },
203 { 0x502e0, 0x2800002f },
204 { 0x5fffc, 0x1bc000c7 },
205 { 0x502e4, 0x2740002c },
206 { 0x5fffc, 0x1cc000c8 },
207 { 0x502e8, 0x26c00029 },
208 { 0x5fffc, 0x1dc000c9 },
209 { 0x502ec, 0x26000027 },
210 { 0x5fffc, 0x1ec000cc },
211 { 0x502f0, 0x25000024 },
212 { 0x5fffc, 0x200000cc },
213 { 0x502f4, 0x24800021 },
214 { 0x5fffc, 0x210000cd },
215 { 0x502f8, 0x23800020 },
216 { 0x5fffc, 0x220000ce },
217 { 0x502fc, 0x2300001d },
218};
219
220static struct mdp_table_entry mdp_downscale_x_table_PT6TOPT8[] = {
221 { 0x5fffc, 0xfe000070 },
222 { 0x50280, 0x4bc00068 },
223 { 0x5fffc, 0xfe000078 },
224 { 0x50284, 0x4bc00060 },
225 { 0x5fffc, 0xfe000080 },
226 { 0x50288, 0x4b800059 },
227 { 0x5fffc, 0xfe000089 },
228 { 0x5028c, 0x4b000052 },
229 { 0x5fffc, 0xfe400091 },
230 { 0x50290, 0x4a80004b },
231 { 0x5fffc, 0xfe40009a },
232 { 0x50294, 0x4a000044 },
233 { 0x5fffc, 0xfe8000a3 },
234 { 0x50298, 0x4940003d },
235 { 0x5fffc, 0xfec000ac },
236 { 0x5029c, 0x48400037 },
237 { 0x5fffc, 0xff0000b4 },
238 { 0x502a0, 0x47800031 },
239 { 0x5fffc, 0xff8000bd },
240 { 0x502a4, 0x4640002b },
241 { 0x5fffc, 0xc5 },
242 { 0x502a8, 0x45000026 },
243 { 0x5fffc, 0x8000ce },
244 { 0x502ac, 0x43800021 },
245 { 0x5fffc, 0x10000d6 },
246 { 0x502b0, 0x4240001c },
247 { 0x5fffc, 0x18000df },
248 { 0x502b4, 0x40800018 },
249 { 0x5fffc, 0x24000e6 },
250 { 0x502b8, 0x3f000014 },
251 { 0x5fffc, 0x30000ee },
252 { 0x502bc, 0x3d400010 },
253 { 0x5fffc, 0x40000f5 },
254 { 0x502c0, 0x3b80000c },
255 { 0x5fffc, 0x50000fc },
256 { 0x502c4, 0x39800009 },
257 { 0x5fffc, 0x6000102 },
258 { 0x502c8, 0x37c00006 },
259 { 0x5fffc, 0x7000109 },
260 { 0x502cc, 0x35800004 },
261 { 0x5fffc, 0x840010e },
262 { 0x502d0, 0x33800002 },
263 { 0x5fffc, 0x9800114 },
264 { 0x502d4, 0x31400000 },
265 { 0x5fffc, 0xac00119 },
266 { 0x502d8, 0x2f4003fe },
267 { 0x5fffc, 0xc40011e },
268 { 0x502dc, 0x2d0003fc },
269 { 0x5fffc, 0xdc00121 },
270 { 0x502e0, 0x2b0003fb },
271 { 0x5fffc, 0xf400125 },
272 { 0x502e4, 0x28c003fa },
273 { 0x5fffc, 0x11000128 },
274 { 0x502e8, 0x268003f9 },
275 { 0x5fffc, 0x12c0012a },
276 { 0x502ec, 0x244003f9 },
277 { 0x5fffc, 0x1480012c },
278 { 0x502f0, 0x224003f8 },
279 { 0x5fffc, 0x1640012e },
280 { 0x502f4, 0x200003f8 },
281 { 0x5fffc, 0x1800012f },
282 { 0x502f8, 0x1e0003f8 },
283 { 0x5fffc, 0x1a00012f },
284 { 0x502fc, 0x1c0003f8 },
285};
286
287static struct mdp_table_entry mdp_downscale_x_table_PT8TO1[] = {
288 { 0x5fffc, 0x0 },
289 { 0x50280, 0x7fc00000 },
290 { 0x5fffc, 0xff80000d },
291 { 0x50284, 0x7ec003f9 },
292 { 0x5fffc, 0xfec0001c },
293 { 0x50288, 0x7d4003f3 },
294 { 0x5fffc, 0xfe40002b },
295 { 0x5028c, 0x7b8003ed },
296 { 0x5fffc, 0xfd80003c },
297 { 0x50290, 0x794003e8 },
298 { 0x5fffc, 0xfcc0004d },
299 { 0x50294, 0x76c003e4 },
300 { 0x5fffc, 0xfc40005f },
301 { 0x50298, 0x73c003e0 },
302 { 0x5fffc, 0xfb800071 },
303 { 0x5029c, 0x708003de },
304 { 0x5fffc, 0xfac00085 },
305 { 0x502a0, 0x6d0003db },
306 { 0x5fffc, 0xfa000098 },
307 { 0x502a4, 0x698003d9 },
308 { 0x5fffc, 0xf98000ac },
309 { 0x502a8, 0x654003d8 },
310 { 0x5fffc, 0xf8c000c1 },
311 { 0x502ac, 0x610003d7 },
312 { 0x5fffc, 0xf84000d5 },
313 { 0x502b0, 0x5c8003d7 },
314 { 0x5fffc, 0xf7c000e9 },
315 { 0x502b4, 0x580003d7 },
316 { 0x5fffc, 0xf74000fd },
317 { 0x502b8, 0x534003d8 },
318 { 0x5fffc, 0xf6c00112 },
319 { 0x502bc, 0x4e8003d8 },
320 { 0x5fffc, 0xf6800126 },
321 { 0x502c0, 0x494003da },
322 { 0x5fffc, 0xf600013a },
323 { 0x502c4, 0x448003db },
324 { 0x5fffc, 0xf600014d },
325 { 0x502c8, 0x3f4003dd },
326 { 0x5fffc, 0xf5c00160 },
327 { 0x502cc, 0x3a4003df },
328 { 0x5fffc, 0xf5c00172 },
329 { 0x502d0, 0x354003e1 },
330 { 0x5fffc, 0xf5c00184 },
331 { 0x502d4, 0x304003e3 },
332 { 0x5fffc, 0xf6000195 },
333 { 0x502d8, 0x2b0003e6 },
334 { 0x5fffc, 0xf64001a6 },
335 { 0x502dc, 0x260003e8 },
336 { 0x5fffc, 0xf6c001b4 },
337 { 0x502e0, 0x214003eb },
338 { 0x5fffc, 0xf78001c2 },
339 { 0x502e4, 0x1c4003ee },
340 { 0x5fffc, 0xf80001cf },
341 { 0x502e8, 0x17c003f1 },
342 { 0x5fffc, 0xf90001db },
343 { 0x502ec, 0x134003f3 },
344 { 0x5fffc, 0xfa0001e5 },
345 { 0x502f0, 0xf0003f6 },
346 { 0x5fffc, 0xfb4001ee },
347 { 0x502f4, 0xac003f9 },
348 { 0x5fffc, 0xfcc001f5 },
349 { 0x502f8, 0x70003fb },
350 { 0x5fffc, 0xfe4001fb },
351 { 0x502fc, 0x34003fe },
352};
353
354struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX] = {
355 [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_x_table_PT2TOPT4,
356 [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_x_table_PT4TOPT6,
357 [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_x_table_PT6TOPT8,
358 [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_x_table_PT8TO1,
359};
360
361static struct mdp_table_entry mdp_downscale_y_table_PT2TOPT4[] = {
362 { 0x5fffc, 0x740008c },
363 { 0x50300, 0x33800088 },
364 { 0x5fffc, 0x800008e },
365 { 0x50304, 0x33400084 },
366 { 0x5fffc, 0x8400092 },
367 { 0x50308, 0x33000080 },
368 { 0x5fffc, 0x9000094 },
369 { 0x5030c, 0x3300007b },
370 { 0x5fffc, 0x9c00098 },
371 { 0x50310, 0x32400077 },
372 { 0x5fffc, 0xa40009b },
373 { 0x50314, 0x32000073 },
374 { 0x5fffc, 0xb00009d },
375 { 0x50318, 0x31c0006f },
376 { 0x5fffc, 0xbc000a0 },
377 { 0x5031c, 0x3140006b },
378 { 0x5fffc, 0xc8000a2 },
379 { 0x50320, 0x31000067 },
380 { 0x5fffc, 0xd8000a5 },
381 { 0x50324, 0x30800062 },
382 { 0x5fffc, 0xe4000a8 },
383 { 0x50328, 0x2fc0005f },
384 { 0x5fffc, 0xec000aa },
385 { 0x5032c, 0x2fc0005b },
386 { 0x5fffc, 0xf8000ad },
387 { 0x50330, 0x2f400057 },
388 { 0x5fffc, 0x108000b0 },
389 { 0x50334, 0x2e400054 },
390 { 0x5fffc, 0x114000b2 },
391 { 0x50338, 0x2e000050 },
392 { 0x5fffc, 0x124000b4 },
393 { 0x5033c, 0x2d80004c },
394 { 0x5fffc, 0x130000b6 },
395 { 0x50340, 0x2d000049 },
396 { 0x5fffc, 0x140000b8 },
397 { 0x50344, 0x2c800045 },
398 { 0x5fffc, 0x150000b9 },
399 { 0x50348, 0x2c000042 },
400 { 0x5fffc, 0x15c000bd },
401 { 0x5034c, 0x2b40003e },
402 { 0x5fffc, 0x16c000bf },
403 { 0x50350, 0x2a80003b },
404 { 0x5fffc, 0x17c000bf },
405 { 0x50354, 0x2a000039 },
406 { 0x5fffc, 0x188000c2 },
407 { 0x50358, 0x29400036 },
408 { 0x5fffc, 0x19c000c4 },
409 { 0x5035c, 0x28800032 },
410 { 0x5fffc, 0x1ac000c5 },
411 { 0x50360, 0x2800002f },
412 { 0x5fffc, 0x1bc000c7 },
413 { 0x50364, 0x2740002c },
414 { 0x5fffc, 0x1cc000c8 },
415 { 0x50368, 0x26c00029 },
416 { 0x5fffc, 0x1dc000c9 },
417 { 0x5036c, 0x26000027 },
418 { 0x5fffc, 0x1ec000cc },
419 { 0x50370, 0x25000024 },
420 { 0x5fffc, 0x200000cc },
421 { 0x50374, 0x24800021 },
422 { 0x5fffc, 0x210000cd },
423 { 0x50378, 0x23800020 },
424 { 0x5fffc, 0x220000ce },
425 { 0x5037c, 0x2300001d },
426};
427
428static struct mdp_table_entry mdp_downscale_y_table_PT4TOPT6[] = {
429 { 0x5fffc, 0x740008c },
430 { 0x50300, 0x33800088 },
431 { 0x5fffc, 0x800008e },
432 { 0x50304, 0x33400084 },
433 { 0x5fffc, 0x8400092 },
434 { 0x50308, 0x33000080 },
435 { 0x5fffc, 0x9000094 },
436 { 0x5030c, 0x3300007b },
437 { 0x5fffc, 0x9c00098 },
438 { 0x50310, 0x32400077 },
439 { 0x5fffc, 0xa40009b },
440 { 0x50314, 0x32000073 },
441 { 0x5fffc, 0xb00009d },
442 { 0x50318, 0x31c0006f },
443 { 0x5fffc, 0xbc000a0 },
444 { 0x5031c, 0x3140006b },
445 { 0x5fffc, 0xc8000a2 },
446 { 0x50320, 0x31000067 },
447 { 0x5fffc, 0xd8000a5 },
448 { 0x50324, 0x30800062 },
449 { 0x5fffc, 0xe4000a8 },
450 { 0x50328, 0x2fc0005f },
451 { 0x5fffc, 0xec000aa },
452 { 0x5032c, 0x2fc0005b },
453 { 0x5fffc, 0xf8000ad },
454 { 0x50330, 0x2f400057 },
455 { 0x5fffc, 0x108000b0 },
456 { 0x50334, 0x2e400054 },
457 { 0x5fffc, 0x114000b2 },
458 { 0x50338, 0x2e000050 },
459 { 0x5fffc, 0x124000b4 },
460 { 0x5033c, 0x2d80004c },
461 { 0x5fffc, 0x130000b6 },
462 { 0x50340, 0x2d000049 },
463 { 0x5fffc, 0x140000b8 },
464 { 0x50344, 0x2c800045 },
465 { 0x5fffc, 0x150000b9 },
466 { 0x50348, 0x2c000042 },
467 { 0x5fffc, 0x15c000bd },
468 { 0x5034c, 0x2b40003e },
469 { 0x5fffc, 0x16c000bf },
470 { 0x50350, 0x2a80003b },
471 { 0x5fffc, 0x17c000bf },
472 { 0x50354, 0x2a000039 },
473 { 0x5fffc, 0x188000c2 },
474 { 0x50358, 0x29400036 },
475 { 0x5fffc, 0x19c000c4 },
476 { 0x5035c, 0x28800032 },
477 { 0x5fffc, 0x1ac000c5 },
478 { 0x50360, 0x2800002f },
479 { 0x5fffc, 0x1bc000c7 },
480 { 0x50364, 0x2740002c },
481 { 0x5fffc, 0x1cc000c8 },
482 { 0x50368, 0x26c00029 },
483 { 0x5fffc, 0x1dc000c9 },
484 { 0x5036c, 0x26000027 },
485 { 0x5fffc, 0x1ec000cc },
486 { 0x50370, 0x25000024 },
487 { 0x5fffc, 0x200000cc },
488 { 0x50374, 0x24800021 },
489 { 0x5fffc, 0x210000cd },
490 { 0x50378, 0x23800020 },
491 { 0x5fffc, 0x220000ce },
492 { 0x5037c, 0x2300001d },
493};
494
495static struct mdp_table_entry mdp_downscale_y_table_PT6TOPT8[] = {
496 { 0x5fffc, 0xfe000070 },
497 { 0x50300, 0x4bc00068 },
498 { 0x5fffc, 0xfe000078 },
499 { 0x50304, 0x4bc00060 },
500 { 0x5fffc, 0xfe000080 },
501 { 0x50308, 0x4b800059 },
502 { 0x5fffc, 0xfe000089 },
503 { 0x5030c, 0x4b000052 },
504 { 0x5fffc, 0xfe400091 },
505 { 0x50310, 0x4a80004b },
506 { 0x5fffc, 0xfe40009a },
507 { 0x50314, 0x4a000044 },
508 { 0x5fffc, 0xfe8000a3 },
509 { 0x50318, 0x4940003d },
510 { 0x5fffc, 0xfec000ac },
511 { 0x5031c, 0x48400037 },
512 { 0x5fffc, 0xff0000b4 },
513 { 0x50320, 0x47800031 },
514 { 0x5fffc, 0xff8000bd },
515 { 0x50324, 0x4640002b },
516 { 0x5fffc, 0xc5 },
517 { 0x50328, 0x45000026 },
518 { 0x5fffc, 0x8000ce },
519 { 0x5032c, 0x43800021 },
520 { 0x5fffc, 0x10000d6 },
521 { 0x50330, 0x4240001c },
522 { 0x5fffc, 0x18000df },
523 { 0x50334, 0x40800018 },
524 { 0x5fffc, 0x24000e6 },
525 { 0x50338, 0x3f000014 },
526 { 0x5fffc, 0x30000ee },
527 { 0x5033c, 0x3d400010 },
528 { 0x5fffc, 0x40000f5 },
529 { 0x50340, 0x3b80000c },
530 { 0x5fffc, 0x50000fc },
531 { 0x50344, 0x39800009 },
532 { 0x5fffc, 0x6000102 },
533 { 0x50348, 0x37c00006 },
534 { 0x5fffc, 0x7000109 },
535 { 0x5034c, 0x35800004 },
536 { 0x5fffc, 0x840010e },
537 { 0x50350, 0x33800002 },
538 { 0x5fffc, 0x9800114 },
539 { 0x50354, 0x31400000 },
540 { 0x5fffc, 0xac00119 },
541 { 0x50358, 0x2f4003fe },
542 { 0x5fffc, 0xc40011e },
543 { 0x5035c, 0x2d0003fc },
544 { 0x5fffc, 0xdc00121 },
545 { 0x50360, 0x2b0003fb },
546 { 0x5fffc, 0xf400125 },
547 { 0x50364, 0x28c003fa },
548 { 0x5fffc, 0x11000128 },
549 { 0x50368, 0x268003f9 },
550 { 0x5fffc, 0x12c0012a },
551 { 0x5036c, 0x244003f9 },
552 { 0x5fffc, 0x1480012c },
553 { 0x50370, 0x224003f8 },
554 { 0x5fffc, 0x1640012e },
555 { 0x50374, 0x200003f8 },
556 { 0x5fffc, 0x1800012f },
557 { 0x50378, 0x1e0003f8 },
558 { 0x5fffc, 0x1a00012f },
559 { 0x5037c, 0x1c0003f8 },
560};
561
562static struct mdp_table_entry mdp_downscale_y_table_PT8TO1[] = {
563 { 0x5fffc, 0x0 },
564 { 0x50300, 0x7fc00000 },
565 { 0x5fffc, 0xff80000d },
566 { 0x50304, 0x7ec003f9 },
567 { 0x5fffc, 0xfec0001c },
568 { 0x50308, 0x7d4003f3 },
569 { 0x5fffc, 0xfe40002b },
570 { 0x5030c, 0x7b8003ed },
571 { 0x5fffc, 0xfd80003c },
572 { 0x50310, 0x794003e8 },
573 { 0x5fffc, 0xfcc0004d },
574 { 0x50314, 0x76c003e4 },
575 { 0x5fffc, 0xfc40005f },
576 { 0x50318, 0x73c003e0 },
577 { 0x5fffc, 0xfb800071 },
578 { 0x5031c, 0x708003de },
579 { 0x5fffc, 0xfac00085 },
580 { 0x50320, 0x6d0003db },
581 { 0x5fffc, 0xfa000098 },
582 { 0x50324, 0x698003d9 },
583 { 0x5fffc, 0xf98000ac },
584 { 0x50328, 0x654003d8 },
585 { 0x5fffc, 0xf8c000c1 },
586 { 0x5032c, 0x610003d7 },
587 { 0x5fffc, 0xf84000d5 },
588 { 0x50330, 0x5c8003d7 },
589 { 0x5fffc, 0xf7c000e9 },
590 { 0x50334, 0x580003d7 },
591 { 0x5fffc, 0xf74000fd },
592 { 0x50338, 0x534003d8 },
593 { 0x5fffc, 0xf6c00112 },
594 { 0x5033c, 0x4e8003d8 },
595 { 0x5fffc, 0xf6800126 },
596 { 0x50340, 0x494003da },
597 { 0x5fffc, 0xf600013a },
598 { 0x50344, 0x448003db },
599 { 0x5fffc, 0xf600014d },
600 { 0x50348, 0x3f4003dd },
601 { 0x5fffc, 0xf5c00160 },
602 { 0x5034c, 0x3a4003df },
603 { 0x5fffc, 0xf5c00172 },
604 { 0x50350, 0x354003e1 },
605 { 0x5fffc, 0xf5c00184 },
606 { 0x50354, 0x304003e3 },
607 { 0x5fffc, 0xf6000195 },
608 { 0x50358, 0x2b0003e6 },
609 { 0x5fffc, 0xf64001a6 },
610 { 0x5035c, 0x260003e8 },
611 { 0x5fffc, 0xf6c001b4 },
612 { 0x50360, 0x214003eb },
613 { 0x5fffc, 0xf78001c2 },
614 { 0x50364, 0x1c4003ee },
615 { 0x5fffc, 0xf80001cf },
616 { 0x50368, 0x17c003f1 },
617 { 0x5fffc, 0xf90001db },
618 { 0x5036c, 0x134003f3 },
619 { 0x5fffc, 0xfa0001e5 },
620 { 0x50370, 0xf0003f6 },
621 { 0x5fffc, 0xfb4001ee },
622 { 0x50374, 0xac003f9 },
623 { 0x5fffc, 0xfcc001f5 },
624 { 0x50378, 0x70003fb },
625 { 0x5fffc, 0xfe4001fb },
626 { 0x5037c, 0x34003fe },
627};
628
629struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX] = {
630 [MDP_DOWNSCALE_PT2TOPT4] = mdp_downscale_y_table_PT2TOPT4,
631 [MDP_DOWNSCALE_PT4TOPT6] = mdp_downscale_y_table_PT4TOPT6,
632 [MDP_DOWNSCALE_PT6TOPT8] = mdp_downscale_y_table_PT6TOPT8,
633 [MDP_DOWNSCALE_PT8TO1] = mdp_downscale_y_table_PT8TO1,
634};
635
636struct mdp_table_entry mdp_gaussian_blur_table[] = {
637 /* max variance */
638 { 0x5fffc, 0x20000080 },
639 { 0x50280, 0x20000080 },
640 { 0x5fffc, 0x20000080 },
641 { 0x50284, 0x20000080 },
642 { 0x5fffc, 0x20000080 },
643 { 0x50288, 0x20000080 },
644 { 0x5fffc, 0x20000080 },
645 { 0x5028c, 0x20000080 },
646 { 0x5fffc, 0x20000080 },
647 { 0x50290, 0x20000080 },
648 { 0x5fffc, 0x20000080 },
649 { 0x50294, 0x20000080 },
650 { 0x5fffc, 0x20000080 },
651 { 0x50298, 0x20000080 },
652 { 0x5fffc, 0x20000080 },
653 { 0x5029c, 0x20000080 },
654 { 0x5fffc, 0x20000080 },
655 { 0x502a0, 0x20000080 },
656 { 0x5fffc, 0x20000080 },
657 { 0x502a4, 0x20000080 },
658 { 0x5fffc, 0x20000080 },
659 { 0x502a8, 0x20000080 },
660 { 0x5fffc, 0x20000080 },
661 { 0x502ac, 0x20000080 },
662 { 0x5fffc, 0x20000080 },
663 { 0x502b0, 0x20000080 },
664 { 0x5fffc, 0x20000080 },
665 { 0x502b4, 0x20000080 },
666 { 0x5fffc, 0x20000080 },
667 { 0x502b8, 0x20000080 },
668 { 0x5fffc, 0x20000080 },
669 { 0x502bc, 0x20000080 },
670 { 0x5fffc, 0x20000080 },
671 { 0x502c0, 0x20000080 },
672 { 0x5fffc, 0x20000080 },
673 { 0x502c4, 0x20000080 },
674 { 0x5fffc, 0x20000080 },
675 { 0x502c8, 0x20000080 },
676 { 0x5fffc, 0x20000080 },
677 { 0x502cc, 0x20000080 },
678 { 0x5fffc, 0x20000080 },
679 { 0x502d0, 0x20000080 },
680 { 0x5fffc, 0x20000080 },
681 { 0x502d4, 0x20000080 },
682 { 0x5fffc, 0x20000080 },
683 { 0x502d8, 0x20000080 },
684 { 0x5fffc, 0x20000080 },
685 { 0x502dc, 0x20000080 },
686 { 0x5fffc, 0x20000080 },
687 { 0x502e0, 0x20000080 },
688 { 0x5fffc, 0x20000080 },
689 { 0x502e4, 0x20000080 },
690 { 0x5fffc, 0x20000080 },
691 { 0x502e8, 0x20000080 },
692 { 0x5fffc, 0x20000080 },
693 { 0x502ec, 0x20000080 },
694 { 0x5fffc, 0x20000080 },
695 { 0x502f0, 0x20000080 },
696 { 0x5fffc, 0x20000080 },
697 { 0x502f4, 0x20000080 },
698 { 0x5fffc, 0x20000080 },
699 { 0x502f8, 0x20000080 },
700 { 0x5fffc, 0x20000080 },
701 { 0x502fc, 0x20000080 },
702 { 0x5fffc, 0x20000080 },
703 { 0x50300, 0x20000080 },
704 { 0x5fffc, 0x20000080 },
705 { 0x50304, 0x20000080 },
706 { 0x5fffc, 0x20000080 },
707 { 0x50308, 0x20000080 },
708 { 0x5fffc, 0x20000080 },
709 { 0x5030c, 0x20000080 },
710 { 0x5fffc, 0x20000080 },
711 { 0x50310, 0x20000080 },
712 { 0x5fffc, 0x20000080 },
713 { 0x50314, 0x20000080 },
714 { 0x5fffc, 0x20000080 },
715 { 0x50318, 0x20000080 },
716 { 0x5fffc, 0x20000080 },
717 { 0x5031c, 0x20000080 },
718 { 0x5fffc, 0x20000080 },
719 { 0x50320, 0x20000080 },
720 { 0x5fffc, 0x20000080 },
721 { 0x50324, 0x20000080 },
722 { 0x5fffc, 0x20000080 },
723 { 0x50328, 0x20000080 },
724 { 0x5fffc, 0x20000080 },
725 { 0x5032c, 0x20000080 },
726 { 0x5fffc, 0x20000080 },
727 { 0x50330, 0x20000080 },
728 { 0x5fffc, 0x20000080 },
729 { 0x50334, 0x20000080 },
730 { 0x5fffc, 0x20000080 },
731 { 0x50338, 0x20000080 },
732 { 0x5fffc, 0x20000080 },
733 { 0x5033c, 0x20000080 },
734 { 0x5fffc, 0x20000080 },
735 { 0x50340, 0x20000080 },
736 { 0x5fffc, 0x20000080 },
737 { 0x50344, 0x20000080 },
738 { 0x5fffc, 0x20000080 },
739 { 0x50348, 0x20000080 },
740 { 0x5fffc, 0x20000080 },
741 { 0x5034c, 0x20000080 },
742 { 0x5fffc, 0x20000080 },
743 { 0x50350, 0x20000080 },
744 { 0x5fffc, 0x20000080 },
745 { 0x50354, 0x20000080 },
746 { 0x5fffc, 0x20000080 },
747 { 0x50358, 0x20000080 },
748 { 0x5fffc, 0x20000080 },
749 { 0x5035c, 0x20000080 },
750 { 0x5fffc, 0x20000080 },
751 { 0x50360, 0x20000080 },
752 { 0x5fffc, 0x20000080 },
753 { 0x50364, 0x20000080 },
754 { 0x5fffc, 0x20000080 },
755 { 0x50368, 0x20000080 },
756 { 0x5fffc, 0x20000080 },
757 { 0x5036c, 0x20000080 },
758 { 0x5fffc, 0x20000080 },
759 { 0x50370, 0x20000080 },
760 { 0x5fffc, 0x20000080 },
761 { 0x50374, 0x20000080 },
762 { 0x5fffc, 0x20000080 },
763 { 0x50378, 0x20000080 },
764 { 0x5fffc, 0x20000080 },
765 { 0x5037c, 0x20000080 },
766};
diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/msm/mdp_scale_tables.h
new file mode 100644
index 000000000000..34077b1af603
--- /dev/null
+++ b/drivers/video/msm/mdp_scale_tables.h
@@ -0,0 +1,38 @@
1/* drivers/video/msm_fb/mdp_scale_tables.h
2 *
3 * Copyright (C) 2007 QUALCOMM Incorporated
4 * Copyright (C) 2007 Google Incorporated
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15#ifndef _MDP_SCALE_TABLES_H_
16#define _MDP_SCALE_TABLES_H_
17
18#include <linux/types.h>
19struct mdp_table_entry {
20 uint32_t reg;
21 uint32_t val;
22};
23
24extern struct mdp_table_entry mdp_upscale_table[64];
25
26enum {
27 MDP_DOWNSCALE_PT2TOPT4,
28 MDP_DOWNSCALE_PT4TOPT6,
29 MDP_DOWNSCALE_PT6TOPT8,
30 MDP_DOWNSCALE_PT8TO1,
31 MDP_DOWNSCALE_MAX,
32};
33
34extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
35extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
36extern struct mdp_table_entry mdp_gaussian_blur_table[];
37
38#endif
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
new file mode 100644
index 000000000000..49101dda45ee
--- /dev/null
+++ b/drivers/video/msm/msm_fb.c
@@ -0,0 +1,636 @@
1/* drivers/video/msm/msm_fb.c
2 *
3 * Core MSM framebuffer driver.
4 *
5 * Copyright (C) 2007 Google Incorporated
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/platform_device.h>
18#include <linux/module.h>
19#include <linux/fb.h>
20#include <linux/delay.h>
21
22#include <linux/freezer.h>
23#include <linux/wait.h>
24#include <linux/msm_mdp.h>
25#include <linux/io.h>
26#include <linux/uaccess.h>
27#include <mach/msm_fb.h>
28#include <mach/board.h>
29#include <linux/workqueue.h>
30#include <linux/clk.h>
31#include <linux/debugfs.h>
32#include <linux/dma-mapping.h>
33
34#define PRINT_FPS 0
35#define PRINT_BLIT_TIME 0
36
37#define SLEEPING 0x4
38#define UPDATING 0x3
39#define FULL_UPDATE_DONE 0x2
40#define WAKING 0x1
41#define AWAKE 0x0
42
43#define NONE 0
44#define SUSPEND_RESUME 0x1
45#define FPS 0x2
46#define BLIT_TIME 0x4
47#define SHOW_UPDATES 0x8
48
49#define DLOG(mask, fmt, args...) \
50do { \
51 if (msmfb_debug_mask & mask) \
52 printk(KERN_INFO "msmfb: "fmt, ##args); \
53} while (0)
54
55static int msmfb_debug_mask;
56module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
57 S_IRUGO | S_IWUSR | S_IWGRP);
58
59struct mdp_device *mdp;
60
61struct msmfb_info {
62 struct fb_info *fb;
63 struct msm_panel_data *panel;
64 int xres;
65 int yres;
66 unsigned output_format;
67 unsigned yoffset;
68 unsigned frame_requested;
69 unsigned frame_done;
70 int sleeping;
71 unsigned update_frame;
72 struct {
73 int left;
74 int top;
75 int eright; /* exclusive */
76 int ebottom; /* exclusive */
77 } update_info;
78 char *black;
79
80 spinlock_t update_lock;
81 struct mutex panel_init_lock;
82 wait_queue_head_t frame_wq;
83 struct workqueue_struct *resume_workqueue;
84 struct work_struct resume_work;
85 struct msmfb_callback dma_callback;
86 struct msmfb_callback vsync_callback;
87 struct hrtimer fake_vsync;
88 ktime_t vsync_request_time;
89};
90
91static int msmfb_open(struct fb_info *info, int user)
92{
93 return 0;
94}
95
96static int msmfb_release(struct fb_info *info, int user)
97{
98 return 0;
99}
100
101/* Called from dma interrupt handler, must not sleep */
102static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
103{
104 unsigned long irq_flags;
105 struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
106 dma_callback);
107
108 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
109 msmfb->frame_done = msmfb->frame_requested;
110 if (msmfb->sleeping == UPDATING &&
111 msmfb->frame_done == msmfb->update_frame) {
112 DLOG(SUSPEND_RESUME, "full update completed\n");
113 queue_work(msmfb->resume_workqueue, &msmfb->resume_work);
114 }
115 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
116 wake_up(&msmfb->frame_wq);
117}
118
119static int msmfb_start_dma(struct msmfb_info *msmfb)
120{
121 uint32_t x, y, w, h;
122 unsigned addr;
123 unsigned long irq_flags;
124 uint32_t yoffset;
125 s64 time_since_request;
126 struct msm_panel_data *panel = msmfb->panel;
127
128 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
129 time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
130 msmfb->vsync_request_time));
131 if (time_since_request > 20 * NSEC_PER_MSEC) {
132 uint32_t us;
133 us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
134 printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
135 "request\n", time_since_request, us);
136 }
137 if (msmfb->frame_done == msmfb->frame_requested) {
138 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
139 return -1;
140 }
141 if (msmfb->sleeping == SLEEPING) {
142 DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
143 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
144 return -1;
145 }
146 x = msmfb->update_info.left;
147 y = msmfb->update_info.top;
148 w = msmfb->update_info.eright - x;
149 h = msmfb->update_info.ebottom - y;
150 yoffset = msmfb->yoffset;
151 msmfb->update_info.left = msmfb->xres + 1;
152 msmfb->update_info.top = msmfb->yres + 1;
153 msmfb->update_info.eright = 0;
154 msmfb->update_info.ebottom = 0;
155 if (unlikely(w > msmfb->xres || h > msmfb->yres ||
156 w == 0 || h == 0)) {
157 printk(KERN_INFO "invalid update: %d %d %d "
158 "%d\n", x, y, w, h);
159 msmfb->frame_done = msmfb->frame_requested;
160 goto error;
161 }
162 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
163
164 addr = ((msmfb->xres * (yoffset + y) + x) * 2);
165 mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
166 msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
167 panel->interface_type);
168 return 0;
169error:
170 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
171 /* some clients need to clear their vsync interrupt */
172 if (panel->clear_vsync)
173 panel->clear_vsync(panel);
174 wake_up(&msmfb->frame_wq);
175 return 0;
176}
177
178/* Called from esync interrupt handler, must not sleep */
179static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
180{
181 struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
182 vsync_callback);
183 msmfb_start_dma(msmfb);
184}
185
186static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
187{
188 struct msmfb_info *msmfb = container_of(timer, struct msmfb_info,
189 fake_vsync);
190 msmfb_start_dma(msmfb);
191 return HRTIMER_NORESTART;
192}
193
194static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
195 uint32_t eright, uint32_t ebottom,
196 uint32_t yoffset, int pan_display)
197{
198 struct msmfb_info *msmfb = info->par;
199 struct msm_panel_data *panel = msmfb->panel;
200 unsigned long irq_flags;
201 int sleeping;
202 int retry = 1;
203
204 DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
205 left, top, eright, ebottom, yoffset, pan_display);
206restart:
207 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
208
209 /* if we are sleeping, on a pan_display wait 10ms (to throttle back
210 * drawing otherwise return */
211 if (msmfb->sleeping == SLEEPING) {
212 DLOG(SUSPEND_RESUME, "drawing while asleep\n");
213 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
214 if (pan_display)
215 wait_event_interruptible_timeout(msmfb->frame_wq,
216 msmfb->sleeping != SLEEPING, HZ/10);
217 return;
218 }
219
220 sleeping = msmfb->sleeping;
221 /* on a full update, if the last frame has not completed, wait for it */
222 if (pan_display && (msmfb->frame_requested != msmfb->frame_done ||
223 sleeping == UPDATING)) {
224 int ret;
225 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
226 ret = wait_event_interruptible_timeout(msmfb->frame_wq,
227 msmfb->frame_done == msmfb->frame_requested &&
228 msmfb->sleeping != UPDATING, 5 * HZ);
229 if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
230 msmfb->sleeping == UPDATING)) {
231 if (retry && panel->request_vsync &&
232 (sleeping == AWAKE)) {
233 panel->request_vsync(panel,
234 &msmfb->vsync_callback);
235 retry = 0;
236 printk(KERN_WARNING "msmfb_pan_display timeout "
237 "rerequest vsync\n");
238 } else {
239 printk(KERN_WARNING "msmfb_pan_display timeout "
240 "waiting for frame start, %d %d\n",
241 msmfb->frame_requested,
242 msmfb->frame_done);
243 return;
244 }
245 }
246 goto restart;
247 }
248
249
250 msmfb->frame_requested++;
251 /* if necessary, update the y offset, if this is the
252 * first full update on resume, set the sleeping state */
253 if (pan_display) {
254 msmfb->yoffset = yoffset;
255 if (left == 0 && top == 0 && eright == info->var.xres &&
256 ebottom == info->var.yres) {
257 if (sleeping == WAKING) {
258 msmfb->update_frame = msmfb->frame_requested;
259 DLOG(SUSPEND_RESUME, "full update starting\n");
260 msmfb->sleeping = UPDATING;
261 }
262 }
263 }
264
265 /* set the update request */
266 if (left < msmfb->update_info.left)
267 msmfb->update_info.left = left;
268 if (top < msmfb->update_info.top)
269 msmfb->update_info.top = top;
270 if (eright > msmfb->update_info.eright)
271 msmfb->update_info.eright = eright;
272 if (ebottom > msmfb->update_info.ebottom)
273 msmfb->update_info.ebottom = ebottom;
274 DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
275 msmfb->update_info.left, msmfb->update_info.top,
276 msmfb->update_info.eright, msmfb->update_info.ebottom,
277 msmfb->yoffset);
278 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
279
280 /* if the panel is all the way on wait for vsync, otherwise sleep
281 * for 16 ms (long enough for the dma to panel) and then begin dma */
282 msmfb->vsync_request_time = ktime_get();
283 if (panel->request_vsync && (sleeping == AWAKE)) {
284 panel->request_vsync(panel, &msmfb->vsync_callback);
285 } else {
286 if (!hrtimer_active(&msmfb->fake_vsync)) {
287 hrtimer_start(&msmfb->fake_vsync,
288 ktime_set(0, NSEC_PER_SEC/60),
289 HRTIMER_MODE_REL);
290 }
291 }
292}
293
294static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
295 uint32_t eright, uint32_t ebottom)
296{
297 msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
298}
299
300static void power_on_panel(struct work_struct *work)
301{
302 struct msmfb_info *msmfb =
303 container_of(work, struct msmfb_info, resume_work);
304 struct msm_panel_data *panel = msmfb->panel;
305 unsigned long irq_flags;
306
307 mutex_lock(&msmfb->panel_init_lock);
308 DLOG(SUSPEND_RESUME, "turning on panel\n");
309 if (msmfb->sleeping == UPDATING) {
310 if (panel->unblank(panel)) {
311 printk(KERN_INFO "msmfb: panel unblank failed,"
312 "not starting drawing\n");
313 goto error;
314 }
315 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
316 msmfb->sleeping = AWAKE;
317 wake_up(&msmfb->frame_wq);
318 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
319 }
320error:
321 mutex_unlock(&msmfb->panel_init_lock);
322}
323
324
325static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
326{
327 if ((var->xres != info->var.xres) ||
328 (var->yres != info->var.yres) ||
329 (var->xres_virtual != info->var.xres_virtual) ||
330 (var->yres_virtual != info->var.yres_virtual) ||
331 (var->xoffset != info->var.xoffset) ||
332 (var->bits_per_pixel != info->var.bits_per_pixel) ||
333 (var->grayscale != info->var.grayscale))
334 return -EINVAL;
335 return 0;
336}
337
338int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
339{
340 struct msmfb_info *msmfb = info->par;
341 struct msm_panel_data *panel = msmfb->panel;
342
343 /* "UPDT" */
344 if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
345 (var->reserved[0] == 0x54445055)) {
346 msmfb_pan_update(info, var->reserved[1] & 0xffff,
347 var->reserved[1] >> 16,
348 var->reserved[2] & 0xffff,
349 var->reserved[2] >> 16, var->yoffset, 1);
350 } else {
351 msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
352 var->yoffset, 1);
353 }
354 return 0;
355}
356
357static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
358{
359 cfb_fillrect(p, rect);
360 msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
361 rect->dy + rect->height);
362}
363
364static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
365{
366 cfb_copyarea(p, area);
367 msmfb_update(p, area->dx, area->dy, area->dx + area->width,
368 area->dy + area->height);
369}
370
371static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
372{
373 cfb_imageblit(p, image);
374 msmfb_update(p, image->dx, image->dy, image->dx + image->width,
375 image->dy + image->height);
376}
377
378
379static int msmfb_blit(struct fb_info *info,
380 void __user *p)
381{
382 struct mdp_blit_req req;
383 struct mdp_blit_req_list req_list;
384 int i;
385 int ret;
386
387 if (copy_from_user(&req_list, p, sizeof(req_list)))
388 return -EFAULT;
389
390 for (i = 0; i < req_list.count; i++) {
391 struct mdp_blit_req_list *list =
392 (struct mdp_blit_req_list *)p;
393 if (copy_from_user(&req, &list->req[i], sizeof(req)))
394 return -EFAULT;
395 ret = mdp->blit(mdp, info, &req);
396 if (ret)
397 return ret;
398 }
399 return 0;
400}
401
402
403DEFINE_MUTEX(mdp_ppp_lock);
404
405static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
406{
407 void __user *argp = (void __user *)arg;
408 int ret;
409
410 switch (cmd) {
411 case MSMFB_GRP_DISP:
412 mdp->set_grp_disp(mdp, arg);
413 break;
414 case MSMFB_BLIT:
415 ret = msmfb_blit(p, argp);
416 if (ret)
417 return ret;
418 break;
419 default:
420 printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
421 return -EINVAL;
422 }
423 return 0;
424}
425
426static struct fb_ops msmfb_ops = {
427 .owner = THIS_MODULE,
428 .fb_open = msmfb_open,
429 .fb_release = msmfb_release,
430 .fb_check_var = msmfb_check_var,
431 .fb_pan_display = msmfb_pan_display,
432 .fb_fillrect = msmfb_fillrect,
433 .fb_copyarea = msmfb_copyarea,
434 .fb_imageblit = msmfb_imageblit,
435 .fb_ioctl = msmfb_ioctl,
436};
437
438static unsigned PP[16];
439
440
441
442#define BITS_PER_PIXEL 16
443
444static void setup_fb_info(struct msmfb_info *msmfb)
445{
446 struct fb_info *fb_info = msmfb->fb;
447 int r;
448
449 /* finish setting up the fb_info struct */
450 strncpy(fb_info->fix.id, "msmfb", 16);
451 fb_info->fix.ypanstep = 1;
452
453 fb_info->fbops = &msmfb_ops;
454 fb_info->flags = FBINFO_DEFAULT;
455
456 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
457 fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
458 fb_info->fix.line_length = msmfb->xres * 2;
459
460 fb_info->var.xres = msmfb->xres;
461 fb_info->var.yres = msmfb->yres;
462 fb_info->var.width = msmfb->panel->fb_data->width;
463 fb_info->var.height = msmfb->panel->fb_data->height;
464 fb_info->var.xres_virtual = msmfb->xres;
465 fb_info->var.yres_virtual = msmfb->yres * 2;
466 fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
467 fb_info->var.accel_flags = 0;
468
469 fb_info->var.yoffset = 0;
470
471 if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
472 fb_info->var.reserved[0] = 0x54445055;
473 fb_info->var.reserved[1] = 0;
474 fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
475 ((uint32_t)msmfb->yres << 16);
476 }
477
478 fb_info->var.red.offset = 11;
479 fb_info->var.red.length = 5;
480 fb_info->var.red.msb_right = 0;
481 fb_info->var.green.offset = 5;
482 fb_info->var.green.length = 6;
483 fb_info->var.green.msb_right = 0;
484 fb_info->var.blue.offset = 0;
485 fb_info->var.blue.length = 5;
486 fb_info->var.blue.msb_right = 0;
487
488 r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
489 fb_info->pseudo_palette = PP;
490
491 PP[0] = 0;
492 for (r = 1; r < 16; r++)
493 PP[r] = 0xffffffff;
494}
495
496static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
497{
498 struct fb_info *fb = msmfb->fb;
499 struct resource *resource;
500 unsigned long size = msmfb->xres * msmfb->yres *
501 (BITS_PER_PIXEL >> 3) * 2;
502 unsigned char *fbram;
503
504 /* board file might have attached a resource describing an fb */
505 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
506 if (!resource)
507 return -EINVAL;
508
509 /* check the resource is large enough to fit the fb */
510 if (resource->end - resource->start < size) {
511 printk(KERN_ERR "allocated resource is too small for "
512 "fb\n");
513 return -ENOMEM;
514 }
515 fb->fix.smem_start = resource->start;
516 fb->fix.smem_len = resource->end - resource->start;
517 fbram = ioremap(resource->start,
518 resource->end - resource->start);
519 if (fbram == 0) {
520 printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
521 return -ENOMEM;
522 }
523 fb->screen_base = fbram;
524 return 0;
525}
526
527static int msmfb_probe(struct platform_device *pdev)
528{
529 struct fb_info *fb;
530 struct msmfb_info *msmfb;
531 struct msm_panel_data *panel = pdev->dev.platform_data;
532 int ret;
533
534 if (!panel) {
535 pr_err("msmfb_probe: no platform data\n");
536 return -EINVAL;
537 }
538 if (!panel->fb_data) {
539 pr_err("msmfb_probe: no fb_data\n");
540 return -EINVAL;
541 }
542
543 fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
544 if (!fb)
545 return -ENOMEM;
546 msmfb = fb->par;
547 msmfb->fb = fb;
548 msmfb->panel = panel;
549 msmfb->xres = panel->fb_data->xres;
550 msmfb->yres = panel->fb_data->yres;
551
552 ret = setup_fbmem(msmfb, pdev);
553 if (ret)
554 goto error_setup_fbmem;
555
556 setup_fb_info(msmfb);
557
558 spin_lock_init(&msmfb->update_lock);
559 mutex_init(&msmfb->panel_init_lock);
560 init_waitqueue_head(&msmfb->frame_wq);
561 msmfb->resume_workqueue = create_workqueue("panel_on");
562 if (msmfb->resume_workqueue == NULL) {
563 printk(KERN_ERR "failed to create panel_on workqueue\n");
564 ret = -ENOMEM;
565 goto error_create_workqueue;
566 }
567 INIT_WORK(&msmfb->resume_work, power_on_panel);
568 msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
569 GFP_KERNEL);
570
571 printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
572 msmfb->xres, msmfb->yres);
573
574 msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
575 msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
576 hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
577 HRTIMER_MODE_REL);
578
579
580 msmfb->fake_vsync.function = msmfb_fake_vsync;
581
582 ret = register_framebuffer(fb);
583 if (ret)
584 goto error_register_framebuffer;
585
586 msmfb->sleeping = WAKING;
587
588 return 0;
589
590error_register_framebuffer:
591 destroy_workqueue(msmfb->resume_workqueue);
592error_create_workqueue:
593 iounmap(fb->screen_base);
594error_setup_fbmem:
595 framebuffer_release(msmfb->fb);
596 return ret;
597}
598
599static struct platform_driver msm_panel_driver = {
600 /* need to write remove */
601 .probe = msmfb_probe,
602 .driver = {.name = "msm_panel"},
603};
604
605
606static int msmfb_add_mdp_device(struct device *dev,
607 struct class_interface *class_intf)
608{
609 /* might need locking if mulitple mdp devices */
610 if (mdp)
611 return 0;
612 mdp = container_of(dev, struct mdp_device, dev);
613 return platform_driver_register(&msm_panel_driver);
614}
615
616static void msmfb_remove_mdp_device(struct device *dev,
617 struct class_interface *class_intf)
618{
619 /* might need locking if mulitple mdp devices */
620 if (dev != &mdp->dev)
621 return;
622 platform_driver_unregister(&msm_panel_driver);
623 mdp = NULL;
624}
625
626static struct class_interface msm_fb_interface = {
627 .add_dev = &msmfb_add_mdp_device,
628 .remove_dev = &msmfb_remove_mdp_device,
629};
630
631static int __init msmfb_init(void)
632{
633 return register_mdp_client(&msm_fb_interface);
634}
635
636module_init(msmfb_init);
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index b7af5256e887..054ef29be479 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -669,7 +669,8 @@ static uint32_t bpp_to_pixfmt(int bpp)
669} 669}
670 670
671static int mx3fb_blank(int blank, struct fb_info *fbi); 671static int mx3fb_blank(int blank, struct fb_info *fbi);
672static int mx3fb_map_video_memory(struct fb_info *fbi); 672static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
673 bool lock);
673static int mx3fb_unmap_video_memory(struct fb_info *fbi); 674static int mx3fb_unmap_video_memory(struct fb_info *fbi);
674 675
675/** 676/**
@@ -711,12 +712,7 @@ static void mx3fb_dma_done(void *arg)
711 complete(&mx3_fbi->flip_cmpl); 712 complete(&mx3_fbi->flip_cmpl);
712} 713}
713 714
714/** 715static int __set_par(struct fb_info *fbi, bool lock)
715 * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
716 * @fbi: framebuffer information pointer.
717 * @return: 0 on success or negative error code on failure.
718 */
719static int mx3fb_set_par(struct fb_info *fbi)
720{ 716{
721 u32 mem_len; 717 u32 mem_len;
722 struct ipu_di_signal_cfg sig_cfg; 718 struct ipu_di_signal_cfg sig_cfg;
@@ -727,10 +723,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
727 struct idmac_video_param *video = &ichan->params.video; 723 struct idmac_video_param *video = &ichan->params.video;
728 struct scatterlist *sg = mx3_fbi->sg; 724 struct scatterlist *sg = mx3_fbi->sg;
729 725
730 dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
731
732 mutex_lock(&mx3_fbi->mutex);
733
734 /* Total cleanup */ 726 /* Total cleanup */
735 if (mx3_fbi->txd) 727 if (mx3_fbi->txd)
736 sdc_disable_channel(mx3_fbi); 728 sdc_disable_channel(mx3_fbi);
@@ -742,11 +734,8 @@ static int mx3fb_set_par(struct fb_info *fbi)
742 if (fbi->fix.smem_start) 734 if (fbi->fix.smem_start)
743 mx3fb_unmap_video_memory(fbi); 735 mx3fb_unmap_video_memory(fbi);
744 736
745 fbi->fix.smem_len = mem_len; 737 if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0)
746 if (mx3fb_map_video_memory(fbi) < 0) {
747 mutex_unlock(&mx3_fbi->mutex);
748 return -ENOMEM; 738 return -ENOMEM;
749 }
750 } 739 }
751 740
752 sg_init_table(&sg[0], 1); 741 sg_init_table(&sg[0], 1);
@@ -792,7 +781,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
792 fbi->var.vsync_len, 781 fbi->var.vsync_len,
793 fbi->var.lower_margin + 782 fbi->var.lower_margin +
794 fbi->var.vsync_len, sig_cfg) != 0) { 783 fbi->var.vsync_len, sig_cfg) != 0) {
795 mutex_unlock(&mx3_fbi->mutex);
796 dev_err(fbi->device, 784 dev_err(fbi->device,
797 "mx3fb: Error initializing panel.\n"); 785 "mx3fb: Error initializing panel.\n");
798 return -EINVAL; 786 return -EINVAL;
@@ -811,9 +799,30 @@ static int mx3fb_set_par(struct fb_info *fbi)
811 if (mx3_fbi->blank == FB_BLANK_UNBLANK) 799 if (mx3_fbi->blank == FB_BLANK_UNBLANK)
812 sdc_enable_channel(mx3_fbi); 800 sdc_enable_channel(mx3_fbi);
813 801
802 return 0;
803}
804
805/**
806 * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
807 * @fbi: framebuffer information pointer.
808 * @return: 0 on success or negative error code on failure.
809 */
810static int mx3fb_set_par(struct fb_info *fbi)
811{
812 struct mx3fb_info *mx3_fbi = fbi->par;
813 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
814 struct idmac_channel *ichan = mx3_fbi->idmac_channel;
815 int ret;
816
817 dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
818
819 mutex_lock(&mx3_fbi->mutex);
820
821 ret = __set_par(fbi, true);
822
814 mutex_unlock(&mx3_fbi->mutex); 823 mutex_unlock(&mx3_fbi->mutex);
815 824
816 return 0; 825 return ret;
817} 826}
818 827
819/** 828/**
@@ -967,21 +976,11 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
967 return ret; 976 return ret;
968} 977}
969 978
970/** 979static void __blank(int blank, struct fb_info *fbi)
971 * mx3fb_blank() - blank the display.
972 */
973static int mx3fb_blank(int blank, struct fb_info *fbi)
974{ 980{
975 struct mx3fb_info *mx3_fbi = fbi->par; 981 struct mx3fb_info *mx3_fbi = fbi->par;
976 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; 982 struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
977 983
978 dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
979 blank, fbi->screen_base, fbi->fix.smem_len);
980
981 if (mx3_fbi->blank == blank)
982 return 0;
983
984 mutex_lock(&mx3_fbi->mutex);
985 mx3_fbi->blank = blank; 984 mx3_fbi->blank = blank;
986 985
987 switch (blank) { 986 switch (blank) {
@@ -1000,6 +999,23 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
1000 sdc_set_brightness(mx3fb, mx3fb->backlight_level); 999 sdc_set_brightness(mx3fb, mx3fb->backlight_level);
1001 break; 1000 break;
1002 } 1001 }
1002}
1003
1004/**
1005 * mx3fb_blank() - blank the display.
1006 */
1007static int mx3fb_blank(int blank, struct fb_info *fbi)
1008{
1009 struct mx3fb_info *mx3_fbi = fbi->par;
1010
1011 dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
1012 blank, fbi->screen_base, fbi->fix.smem_len);
1013
1014 if (mx3_fbi->blank == blank)
1015 return 0;
1016
1017 mutex_lock(&mx3_fbi->mutex);
1018 __blank(blank, fbi);
1003 mutex_unlock(&mx3_fbi->mutex); 1019 mutex_unlock(&mx3_fbi->mutex);
1004 1020
1005 return 0; 1021 return 0;
@@ -1198,6 +1214,8 @@ static int mx3fb_resume(struct platform_device *pdev)
1198/** 1214/**
1199 * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. 1215 * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
1200 * @fbi: framebuffer information pointer 1216 * @fbi: framebuffer information pointer
1217 * @mem_len: length of mapped memory
1218 * @lock: do not lock during initialisation
1201 * @return: Error code indicating success or failure 1219 * @return: Error code indicating success or failure
1202 * 1220 *
1203 * This buffer is remapped into a non-cached, non-buffered, memory region to 1221 * This buffer is remapped into a non-cached, non-buffered, memory region to
@@ -1205,23 +1223,29 @@ static int mx3fb_resume(struct platform_device *pdev)
1205 * area is remapped, all virtual memory access to the video memory should occur 1223 * area is remapped, all virtual memory access to the video memory should occur
1206 * at the new region. 1224 * at the new region.
1207 */ 1225 */
1208static int mx3fb_map_video_memory(struct fb_info *fbi) 1226static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
1227 bool lock)
1209{ 1228{
1210 int retval = 0; 1229 int retval = 0;
1211 dma_addr_t addr; 1230 dma_addr_t addr;
1212 1231
1213 fbi->screen_base = dma_alloc_writecombine(fbi->device, 1232 fbi->screen_base = dma_alloc_writecombine(fbi->device,
1214 fbi->fix.smem_len, 1233 mem_len,
1215 &addr, GFP_DMA); 1234 &addr, GFP_DMA);
1216 1235
1217 if (!fbi->screen_base) { 1236 if (!fbi->screen_base) {
1218 dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", 1237 dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
1219 fbi->fix.smem_len); 1238 mem_len);
1220 retval = -EBUSY; 1239 retval = -EBUSY;
1221 goto err0; 1240 goto err0;
1222 } 1241 }
1223 1242
1243 if (lock)
1244 mutex_lock(&fbi->mm_lock);
1224 fbi->fix.smem_start = addr; 1245 fbi->fix.smem_start = addr;
1246 fbi->fix.smem_len = mem_len;
1247 if (lock)
1248 mutex_unlock(&fbi->mm_lock);
1225 1249
1226 dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", 1250 dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
1227 (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); 1251 (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
@@ -1251,8 +1275,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi)
1251 fbi->screen_base, fbi->fix.smem_start); 1275 fbi->screen_base, fbi->fix.smem_start);
1252 1276
1253 fbi->screen_base = 0; 1277 fbi->screen_base = 0;
1278 mutex_lock(&fbi->mm_lock);
1254 fbi->fix.smem_start = 0; 1279 fbi->fix.smem_start = 0;
1255 fbi->fix.smem_len = 0; 1280 fbi->fix.smem_len = 0;
1281 mutex_unlock(&fbi->mm_lock);
1256 return 0; 1282 return 0;
1257} 1283}
1258 1284
@@ -1360,11 +1386,11 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
1360 init_completion(&mx3fbi->flip_cmpl); 1386 init_completion(&mx3fbi->flip_cmpl);
1361 disable_irq(ichan->eof_irq); 1387 disable_irq(ichan->eof_irq);
1362 dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); 1388 dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
1363 ret = mx3fb_set_par(fbi); 1389 ret = __set_par(fbi, false);
1364 if (ret < 0) 1390 if (ret < 0)
1365 goto esetpar; 1391 goto esetpar;
1366 1392
1367 mx3fb_blank(FB_BLANK_UNBLANK, fbi); 1393 __blank(FB_BLANK_UNBLANK, fbi);
1368 1394
1369 dev_info(dev, "registered, using mode %s\n", fb_mode); 1395 dev_info(dev, "registered, using mode %s\n", fb_mode);
1370 1396
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 44408850e2eb..551e3e9c4cbe 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -7,6 +7,69 @@ config FB_OMAP
7 help 7 help
8 Frame buffer driver for OMAP based boards. 8 Frame buffer driver for OMAP based boards.
9 9
10config FB_OMAP_LCD_VGA
11 bool "Use LCD in VGA mode"
12 depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP
13
14choice
15 depends on FB_OMAP && MACH_OVERO
16 prompt "Screen resolution"
17 default FB_OMAP_079M3R
18 help
19 Selected desired screen resolution
20
21config FB_OMAP_031M3R
22 boolean "640 x 480 @ 60 Hz Reduced blanking"
23
24config FB_OMAP_048M3R
25 boolean "800 x 600 @ 60 Hz Reduced blanking"
26
27config FB_OMAP_079M3R
28 boolean "1024 x 768 @ 60 Hz Reduced blanking"
29
30config FB_OMAP_092M9R
31 boolean "1280 x 720 @ 60 Hz Reduced blanking"
32
33endchoice
34
35config FB_OMAP_LCDC_EXTERNAL
36 bool "External LCD controller support"
37 depends on FB_OMAP
38 help
39 Say Y here, if you want to have support for boards with an
40 external LCD controller connected to the SoSSI/RFBI interface.
41
42config FB_OMAP_LCDC_HWA742
43 bool "Epson HWA742 LCD controller support"
44 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
45 help
46 Say Y here if you want to have support for the external
47 Epson HWA742 LCD controller.
48
49config FB_OMAP_LCDC_BLIZZARD
50 bool "Epson Blizzard LCD controller support"
51 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
52 help
53 Say Y here if you want to have support for the external
54 Epson Blizzard LCD controller.
55
56config FB_OMAP_MANUAL_UPDATE
57 bool "Default to manual update mode"
58 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
59 help
60 Say Y here, if your user-space applications are capable of
61 notifying the frame buffer driver when a change has occured in
62 the frame buffer content and thus a reload of the image data to
63 the external frame buffer is required. If unsure, say N.
64
65config FB_OMAP_LCD_MIPID
66 bool "MIPI DBI-C/DCS compatible LCD support"
67 depends on FB_OMAP && SPI_MASTER
68 help
69 Say Y here if you want to have support for LCDs compatible with
70 the Mobile Industry Processor Interface DBI-C/DCS
71 specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
72
10config FB_OMAP_BOOTLOADER_INIT 73config FB_OMAP_BOOTLOADER_INIT
11 bool "Check bootloader initialization" 74 bool "Check bootloader initialization"
12 depends on FB_OMAP 75 depends on FB_OMAP
@@ -36,23 +99,4 @@ config FB_OMAP_DMA_TUNE
36 answer yes. Answer no if you have a dedicated video 99 answer yes. Answer no if you have a dedicated video
37 memory, or don't use any of the accelerated features. 100 memory, or don't use any of the accelerated features.
38 101
39config FB_OMAP_LCDC_EXTERNAL
40 bool "External LCD controller support"
41 depends on FB_OMAP
42 help
43 Say Y here, if you want to have support for boards with an
44 external LCD controller connected to the SoSSI/RFBI interface.
45
46config FB_OMAP_LCDC_HWA742
47 bool "Epson HWA742 LCD controller support"
48 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
49 help
50 Say Y here if you want to have support for the external
51 Epson HWA742 LCD controller.
52 102
53config FB_OMAP_LCDC_BLIZZARD
54 bool "Epson Blizzard LCD controller support"
55 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
56 help
57 Say Y here if you want to have support for the external
58 Epson Blizzard LCD controller.
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index ed13889c1162..b63b198d1f03 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -8,6 +8,7 @@ objs-yy := omapfb_main.o
8 8
9objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o 9objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o
10objs-y$(CONFIG_ARCH_OMAP2) += dispc.o 10objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
11objs-y$(CONFIG_ARCH_OMAP3) += dispc.o
11 12
12objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o 13objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
13objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o 14objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
@@ -15,6 +16,7 @@ objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
15objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o 16objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
16objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o 17objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
17 18
19objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
18objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o 20objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
19objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o 21objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
20objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o 22objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
@@ -24,5 +26,15 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
24objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o 26objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
25objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o 27objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
26 28
29objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
30objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o
31objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o
32objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o
33objs-y$(CONFIG_MACH_OMAP2EVM) += lcd_omap2evm.o
34objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o
35objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o
36objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
37objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o
38
27omapfb-objs := $(objs-yy) 39omapfb-objs := $(objs-yy)
28 40
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 9dfcf39d3367..70dadf9d2334 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -44,6 +44,7 @@
44#define BLIZZARD_CLK_SRC 0x0e 44#define BLIZZARD_CLK_SRC 0x0e
45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
46#define BLIZZARD_MEM_BANK0_STATUS 0x14 46#define BLIZZARD_MEM_BANK0_STATUS 0x14
47#define BLIZZARD_PANEL_CONFIGURATION 0x28
47#define BLIZZARD_HDISP 0x2a 48#define BLIZZARD_HDISP 0x2a
48#define BLIZZARD_HNDP 0x2c 49#define BLIZZARD_HNDP 0x2c
49#define BLIZZARD_VDISP0 0x2e 50#define BLIZZARD_VDISP0 0x2e
@@ -92,7 +93,7 @@ struct blizzard_reg_list {
92}; 93};
93 94
94/* These need to be saved / restored separately from the rest. */ 95/* These need to be saved / restored separately from the rest. */
95static struct blizzard_reg_list blizzard_pll_regs[] = { 96static const struct blizzard_reg_list blizzard_pll_regs[] = {
96 { 97 {
97 .start = 0x04, /* Don't save PLL ctrl (0x0C) */ 98 .start = 0x04, /* Don't save PLL ctrl (0x0C) */
98 .end = 0x0a, 99 .end = 0x0a,
@@ -103,7 +104,7 @@ static struct blizzard_reg_list blizzard_pll_regs[] = {
103 }, 104 },
104}; 105};
105 106
106static struct blizzard_reg_list blizzard_gen_regs[] = { 107static const struct blizzard_reg_list blizzard_gen_regs[] = {
107 { 108 {
108 .start = 0x18, /* SDRAM control */ 109 .start = 0x18, /* SDRAM control */
109 .end = 0x20, 110 .end = 0x20,
@@ -162,6 +163,10 @@ struct blizzard_struct {
162 int vid_scaled; 163 int vid_scaled;
163 int last_color_mode; 164 int last_color_mode;
164 int zoom_on; 165 int zoom_on;
166 int zoom_area_gx1;
167 int zoom_area_gx2;
168 int zoom_area_gy1;
169 int zoom_area_gy2;
165 int screen_width; 170 int screen_width;
166 int screen_height; 171 int screen_height;
167 unsigned te_connected:1; 172 unsigned te_connected:1;
@@ -186,7 +191,7 @@ struct blizzard_struct {
186 191
187 struct omapfb_device *fbdev; 192 struct omapfb_device *fbdev;
188 struct lcd_ctrl_extif *extif; 193 struct lcd_ctrl_extif *extif;
189 struct lcd_ctrl *int_ctrl; 194 const struct lcd_ctrl *int_ctrl;
190 195
191 void (*power_up)(struct device *dev); 196 void (*power_up)(struct device *dev);
192 void (*power_down)(struct device *dev); 197 void (*power_down)(struct device *dev);
@@ -513,6 +518,13 @@ static int do_full_screen_update(struct blizzard_request *req)
513 return REQ_PENDING; 518 return REQ_PENDING;
514} 519}
515 520
521static int check_1d_intersect(int a1, int a2, int b1, int b2)
522{
523 if (a2 <= b1 || b2 <= a1)
524 return 0;
525 return 1;
526}
527
516/* Setup all planes with an overlapping area with the update window. */ 528/* Setup all planes with an overlapping area with the update window. */
517static int do_partial_update(struct blizzard_request *req, int plane, 529static int do_partial_update(struct blizzard_request *req, int plane,
518 int x, int y, int w, int h, 530 int x, int y, int w, int h,
@@ -525,6 +537,7 @@ static int do_partial_update(struct blizzard_request *req, int plane,
525 int color_mode; 537 int color_mode;
526 int flags; 538 int flags;
527 int zoom_off; 539 int zoom_off;
540 int have_zoom_for_this_update = 0;
528 541
529 /* Global coordinates, relative to pixel 0,0 of the LCD */ 542 /* Global coordinates, relative to pixel 0,0 of the LCD */
530 gx1 = x + blizzard.plane[plane].pos_x; 543 gx1 = x + blizzard.plane[plane].pos_x;
@@ -544,10 +557,6 @@ static int do_partial_update(struct blizzard_request *req, int plane,
544 gx2_out = gx1_out + w_out; 557 gx2_out = gx1_out + w_out;
545 gy2_out = gy1_out + h_out; 558 gy2_out = gy1_out + h_out;
546 } 559 }
547 zoom_off = blizzard.zoom_on && gx1 == 0 && gy1 == 0 &&
548 w == blizzard.screen_width && h == blizzard.screen_height;
549 blizzard.zoom_on = (!zoom_off && blizzard.zoom_on) ||
550 (w < w_out || h < h_out);
551 560
552 for (i = 0; i < OMAPFB_PLANE_NUM; i++) { 561 for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
553 struct plane_info *p = &blizzard.plane[i]; 562 struct plane_info *p = &blizzard.plane[i];
@@ -653,8 +662,49 @@ static int do_partial_update(struct blizzard_request *req, int plane,
653 else 662 else
654 disable_tearsync(); 663 disable_tearsync();
655 664
665 if ((gx2_out - gx1_out) != (gx2 - gx1) ||
666 (gy2_out - gy1_out) != (gy2 - gy1))
667 have_zoom_for_this_update = 1;
668
669 /* 'background' type of screen update (as opposed to 'destructive')
670 can be used to disable scaling if scaling is active */
671 zoom_off = blizzard.zoom_on && !have_zoom_for_this_update &&
672 (gx1_out == 0) && (gx2_out == blizzard.screen_width) &&
673 (gy1_out == 0) && (gy2_out == blizzard.screen_height) &&
674 (gx1 == 0) && (gy1 == 0);
675
676 if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off &&
677 check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2,
678 gx1_out, gx2_out) &&
679 check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2,
680 gy1_out, gy2_out)) {
681 /* Previous screen update was using scaling, current update
682 * is not using it. Additionally, current screen update is
683 * going to overlap with the scaled area. Scaling needs to be
684 * disabled in order to avoid 'magnifying glass' effect.
685 * Dummy setup of background window can be used for this.
686 */
687 set_window_regs(0, 0, blizzard.screen_width,
688 blizzard.screen_height,
689 0, 0, blizzard.screen_width,
690 blizzard.screen_height,
691 BLIZZARD_COLOR_RGB565, 1, flags);
692 blizzard.zoom_on = 0;
693 }
694
695 /* remember scaling settings if we have scaled update */
696 if (have_zoom_for_this_update) {
697 blizzard.zoom_on = 1;
698 blizzard.zoom_area_gx1 = gx1_out;
699 blizzard.zoom_area_gx2 = gx2_out;
700 blizzard.zoom_area_gy1 = gy1_out;
701 blizzard.zoom_area_gy2 = gy2_out;
702 }
703
656 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out, 704 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
657 color_mode, zoom_off, flags); 705 color_mode, zoom_off, flags);
706 if (zoom_off)
707 blizzard.zoom_on = 0;
658 708
659 blizzard.extif->set_bits_per_cycle(16); 709 blizzard.extif->set_bits_per_cycle(16);
660 /* set_window_regs has left the register index at the right 710 /* set_window_regs has left the register index at the right
@@ -908,6 +958,35 @@ static int blizzard_set_scale(int plane, int orig_w, int orig_h,
908 return 0; 958 return 0;
909} 959}
910 960
961static int blizzard_set_rotate(int angle)
962{
963 u32 l;
964
965 l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION);
966 l &= ~0x03;
967
968 switch (angle) {
969 case 0:
970 l = l | 0x00;
971 break;
972 case 90:
973 l = l | 0x03;
974 break;
975 case 180:
976 l = l | 0x02;
977 break;
978 case 270:
979 l = l | 0x01;
980 break;
981 default:
982 return -EINVAL;
983 }
984
985 blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l);
986
987 return 0;
988}
989
911static int blizzard_enable_plane(int plane, int enable) 990static int blizzard_enable_plane(int plane, int enable)
912{ 991{
913 if (enable) 992 if (enable)
@@ -1285,14 +1364,15 @@ static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
1285 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE | 1364 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
1286 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE | 1365 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
1287 OMAPFB_CAPS_WINDOW_SCALE | 1366 OMAPFB_CAPS_WINDOW_SCALE |
1288 OMAPFB_CAPS_WINDOW_OVERLAY; 1367 OMAPFB_CAPS_WINDOW_OVERLAY |
1368 OMAPFB_CAPS_WINDOW_ROTATE;
1289 if (blizzard.te_connected) 1369 if (blizzard.te_connected)
1290 caps->ctrl |= OMAPFB_CAPS_TEARSYNC; 1370 caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
1291 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) | 1371 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
1292 (1 << OMAPFB_COLOR_YUV420); 1372 (1 << OMAPFB_COLOR_YUV420);
1293} 1373}
1294 1374
1295static void _save_regs(struct blizzard_reg_list *list, int cnt) 1375static void _save_regs(const struct blizzard_reg_list *list, int cnt)
1296{ 1376{
1297 int i; 1377 int i;
1298 1378
@@ -1303,7 +1383,7 @@ static void _save_regs(struct blizzard_reg_list *list, int cnt)
1303 } 1383 }
1304} 1384}
1305 1385
1306static void _restore_regs(struct blizzard_reg_list *list, int cnt) 1386static void _restore_regs(const struct blizzard_reg_list *list, int cnt)
1307{ 1387{
1308 int i; 1388 int i;
1309 1389
@@ -1560,6 +1640,7 @@ struct lcd_ctrl blizzard_ctrl = {
1560 .setup_plane = blizzard_setup_plane, 1640 .setup_plane = blizzard_setup_plane,
1561 .set_scale = blizzard_set_scale, 1641 .set_scale = blizzard_set_scale,
1562 .enable_plane = blizzard_enable_plane, 1642 .enable_plane = blizzard_enable_plane,
1643 .set_rotate = blizzard_set_rotate,
1563 .update_window = blizzard_update_window_async, 1644 .update_window = blizzard_update_window_async,
1564 .sync = blizzard_sync, 1645 .sync = blizzard_sync,
1565 .suspend = blizzard_suspend, 1646 .suspend = blizzard_suspend,
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index 148cbcc39602..f16e42154229 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -155,6 +155,8 @@ struct resmap {
155 unsigned long *map; 155 unsigned long *map;
156}; 156};
157 157
158#define MAX_IRQ_HANDLERS 4
159
158static struct { 160static struct {
159 void __iomem *base; 161 void __iomem *base;
160 162
@@ -167,9 +169,11 @@ static struct {
167 169
168 int ext_mode; 170 int ext_mode;
169 171
170 unsigned long enabled_irqs; 172 struct {
171 void (*irq_callback)(void *); 173 u32 irq_mask;
172 void *irq_callback_data; 174 void (*callback)(void *);
175 void *data;
176 } irq_handlers[MAX_IRQ_HANDLERS];
173 struct completion frame_done; 177 struct completion frame_done;
174 178
175 int fir_hinc[OMAPFB_PLANE_NUM]; 179 int fir_hinc[OMAPFB_PLANE_NUM];
@@ -212,9 +216,9 @@ static void enable_rfbi_mode(int enable)
212 dispc_write_reg(DISPC_CONTROL, l); 216 dispc_write_reg(DISPC_CONTROL, l);
213 217
214 /* Set bypass mode in RFBI module */ 218 /* Set bypass mode in RFBI module */
215 l = __raw_readl(IO_ADDRESS(RFBI_CONTROL)); 219 l = __raw_readl(OMAP2_IO_ADDRESS(RFBI_CONTROL));
216 l |= enable ? 0 : (1 << 1); 220 l |= enable ? 0 : (1 << 1);
217 __raw_writel(l, IO_ADDRESS(RFBI_CONTROL)); 221 __raw_writel(l, OMAP2_IO_ADDRESS(RFBI_CONTROL));
218} 222}
219 223
220static void set_lcd_data_lines(int data_lines) 224static void set_lcd_data_lines(int data_lines)
@@ -286,7 +290,7 @@ static void setup_plane_fifo(int plane, int ext_mode)
286 BUG_ON(plane > 2); 290 BUG_ON(plane > 2);
287 291
288 l = dispc_read_reg(fsz_reg[plane]); 292 l = dispc_read_reg(fsz_reg[plane]);
289 l &= FLD_MASK(0, 9); 293 l &= FLD_MASK(0, 11);
290 if (ext_mode) { 294 if (ext_mode) {
291 low = l * 3 / 4; 295 low = l * 3 / 4;
292 high = l; 296 high = l;
@@ -294,7 +298,7 @@ static void setup_plane_fifo(int plane, int ext_mode)
294 low = l / 4; 298 low = l / 4;
295 high = l * 3 / 4; 299 high = l * 3 / 4;
296 } 300 }
297 MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 9) | FLD_MASK(0, 9), 301 MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12),
298 (high << 16) | low); 302 (high << 16) | low);
299} 303}
300 304
@@ -809,57 +813,74 @@ static void set_lcd_timings(void)
809 panel->pixel_clock = fck / lck_div / pck_div / 1000; 813 panel->pixel_clock = fck / lck_div / pck_div / 1000;
810} 814}
811 815
812int omap_dispc_request_irq(void (*callback)(void *data), void *data) 816static void recalc_irq_mask(void)
813{ 817{
814 int r = 0; 818 int i;
819 unsigned long irq_mask = DISPC_IRQ_MASK_ERROR;
815 820
816 BUG_ON(callback == NULL); 821 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
822 if (!dispc.irq_handlers[i].callback)
823 continue;
817 824
818 if (dispc.irq_callback) 825 irq_mask |= dispc.irq_handlers[i].irq_mask;
819 r = -EBUSY;
820 else {
821 dispc.irq_callback = callback;
822 dispc.irq_callback_data = data;
823 } 826 }
824 827
825 return r;
826}
827EXPORT_SYMBOL(omap_dispc_request_irq);
828
829void omap_dispc_enable_irqs(int irq_mask)
830{
831 enable_lcd_clocks(1); 828 enable_lcd_clocks(1);
832 dispc.enabled_irqs = irq_mask;
833 irq_mask |= DISPC_IRQ_MASK_ERROR;
834 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); 829 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
835 enable_lcd_clocks(0); 830 enable_lcd_clocks(0);
836} 831}
837EXPORT_SYMBOL(omap_dispc_enable_irqs);
838 832
839void omap_dispc_disable_irqs(int irq_mask) 833int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data),
834 void *data)
840{ 835{
841 enable_lcd_clocks(1); 836 int i;
842 dispc.enabled_irqs &= ~irq_mask; 837
843 irq_mask &= ~DISPC_IRQ_MASK_ERROR; 838 BUG_ON(callback == NULL);
844 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask); 839
845 enable_lcd_clocks(0); 840 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
841 if (dispc.irq_handlers[i].callback)
842 continue;
843
844 dispc.irq_handlers[i].irq_mask = irq_mask;
845 dispc.irq_handlers[i].callback = callback;
846 dispc.irq_handlers[i].data = data;
847 recalc_irq_mask();
848
849 return 0;
850 }
851
852 return -EBUSY;
846} 853}
847EXPORT_SYMBOL(omap_dispc_disable_irqs); 854EXPORT_SYMBOL(omap_dispc_request_irq);
848 855
849void omap_dispc_free_irq(void) 856void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data),
857 void *data)
850{ 858{
851 enable_lcd_clocks(1); 859 int i;
852 omap_dispc_disable_irqs(DISPC_IRQ_MASK_ALL); 860
853 dispc.irq_callback = NULL; 861 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
854 dispc.irq_callback_data = NULL; 862 if (dispc.irq_handlers[i].callback == callback &&
855 enable_lcd_clocks(0); 863 dispc.irq_handlers[i].data == data) {
864 dispc.irq_handlers[i].irq_mask = 0;
865 dispc.irq_handlers[i].callback = NULL;
866 dispc.irq_handlers[i].data = NULL;
867 recalc_irq_mask();
868 return;
869 }
870 }
871
872 BUG();
856} 873}
857EXPORT_SYMBOL(omap_dispc_free_irq); 874EXPORT_SYMBOL(omap_dispc_free_irq);
858 875
859static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) 876static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
860{ 877{
861 u32 stat = dispc_read_reg(DISPC_IRQSTATUS); 878 u32 stat;
879 int i = 0;
880
881 enable_lcd_clocks(1);
862 882
883 stat = dispc_read_reg(DISPC_IRQSTATUS);
863 if (stat & DISPC_IRQ_FRAMEMASK) 884 if (stat & DISPC_IRQ_FRAMEMASK)
864 complete(&dispc.frame_done); 885 complete(&dispc.frame_done);
865 886
@@ -870,11 +891,17 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
870 } 891 }
871 } 892 }
872 893
873 if ((stat & dispc.enabled_irqs) && dispc.irq_callback) 894 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
874 dispc.irq_callback(dispc.irq_callback_data); 895 if (unlikely(dispc.irq_handlers[i].callback &&
896 (stat & dispc.irq_handlers[i].irq_mask)))
897 dispc.irq_handlers[i].callback(
898 dispc.irq_handlers[i].data);
899 }
875 900
876 dispc_write_reg(DISPC_IRQSTATUS, stat); 901 dispc_write_reg(DISPC_IRQSTATUS, stat);
877 902
903 enable_lcd_clocks(0);
904
878 return IRQ_HANDLED; 905 return IRQ_HANDLED;
879} 906}
880 907
@@ -913,18 +940,13 @@ static void put_dss_clocks(void)
913 940
914static void enable_lcd_clocks(int enable) 941static void enable_lcd_clocks(int enable)
915{ 942{
916 if (enable) 943 if (enable) {
944 clk_enable(dispc.dss_ick);
917 clk_enable(dispc.dss1_fck); 945 clk_enable(dispc.dss1_fck);
918 else 946 } else {
919 clk_disable(dispc.dss1_fck); 947 clk_disable(dispc.dss1_fck);
920}
921
922static void enable_interface_clocks(int enable)
923{
924 if (enable)
925 clk_enable(dispc.dss_ick);
926 else
927 clk_disable(dispc.dss_ick); 948 clk_disable(dispc.dss_ick);
949 }
928} 950}
929 951
930static void enable_digit_clocks(int enable) 952static void enable_digit_clocks(int enable)
@@ -1013,7 +1035,7 @@ static void mmap_user_close(struct vm_area_struct *vma)
1013 atomic_dec(&dispc.map_count[plane]); 1035 atomic_dec(&dispc.map_count[plane]);
1014} 1036}
1015 1037
1016static struct vm_operations_struct mmap_user_ops = { 1038static const struct vm_operations_struct mmap_user_ops = {
1017 .open = mmap_user_open, 1039 .open = mmap_user_open,
1018 .close = mmap_user_close, 1040 .close = mmap_user_close,
1019}; 1041};
@@ -1365,7 +1387,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1365 if ((r = get_dss_clocks()) < 0) 1387 if ((r = get_dss_clocks()) < 0)
1366 goto fail0; 1388 goto fail0;
1367 1389
1368 enable_interface_clocks(1);
1369 enable_lcd_clocks(1); 1390 enable_lcd_clocks(1);
1370 1391
1371#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT 1392#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
@@ -1396,10 +1417,10 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1396 enable_digit_clocks(0); 1417 enable_digit_clocks(0);
1397 } 1418 }
1398 1419
1399 /* Enable smart idle and autoidle */ 1420 /* Enable smart standby/idle, autoidle and wakeup */
1400 l = dispc_read_reg(DISPC_CONTROL); 1421 l = dispc_read_reg(DISPC_SYSCONFIG);
1401 l &= ~((3 << 12) | (3 << 3)); 1422 l &= ~((3 << 12) | (3 << 3));
1402 l |= (2 << 12) | (2 << 3) | (1 << 0); 1423 l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0);
1403 dispc_write_reg(DISPC_SYSCONFIG, l); 1424 dispc_write_reg(DISPC_SYSCONFIG, l);
1404 omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG); 1425 omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
1405 1426
@@ -1409,10 +1430,9 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1409 dispc_write_reg(DISPC_CONFIG, l); 1430 dispc_write_reg(DISPC_CONFIG, l);
1410 1431
1411 l = dispc_read_reg(DISPC_IRQSTATUS); 1432 l = dispc_read_reg(DISPC_IRQSTATUS);
1412 dispc_write_reg(l, DISPC_IRQSTATUS); 1433 dispc_write_reg(DISPC_IRQSTATUS, l);
1413 1434
1414 /* Enable those that we handle always */ 1435 recalc_irq_mask();
1415 omap_dispc_enable_irqs(DISPC_IRQ_FRAMEMASK);
1416 1436
1417 if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler, 1437 if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
1418 0, MODULE_NAME, fbdev)) < 0) { 1438 0, MODULE_NAME, fbdev)) < 0) {
@@ -1421,7 +1441,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1421 } 1441 }
1422 1442
1423 /* L3 firewall setting: enable access to OCM RAM */ 1443 /* L3 firewall setting: enable access to OCM RAM */
1424 __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0)); 1444 __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0));
1425 1445
1426 if ((r = alloc_palette_ram()) < 0) 1446 if ((r = alloc_palette_ram()) < 0)
1427 goto fail2; 1447 goto fail2;
@@ -1469,7 +1489,6 @@ fail2:
1469 free_irq(INT_24XX_DSS_IRQ, fbdev); 1489 free_irq(INT_24XX_DSS_IRQ, fbdev);
1470fail1: 1490fail1:
1471 enable_lcd_clocks(0); 1491 enable_lcd_clocks(0);
1472 enable_interface_clocks(0);
1473 put_dss_clocks(); 1492 put_dss_clocks();
1474fail0: 1493fail0:
1475 iounmap(dispc.base); 1494 iounmap(dispc.base);
@@ -1487,7 +1506,6 @@ static void omap_dispc_cleanup(void)
1487 cleanup_fbmem(); 1506 cleanup_fbmem();
1488 free_palette_ram(); 1507 free_palette_ram();
1489 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); 1508 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
1490 enable_interface_clocks(0);
1491 put_dss_clocks(); 1509 put_dss_clocks();
1492 iounmap(dispc.base); 1510 iounmap(dispc.base);
1493} 1511}
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
index ef720a78f6d5..c15ea77f0604 100644
--- a/drivers/video/omap/dispc.h
+++ b/drivers/video/omap/dispc.h
@@ -37,9 +37,10 @@ extern void omap_dispc_set_lcd_size(int width, int height);
37extern void omap_dispc_enable_lcd_out(int enable); 37extern void omap_dispc_enable_lcd_out(int enable);
38extern void omap_dispc_enable_digit_out(int enable); 38extern void omap_dispc_enable_digit_out(int enable);
39 39
40extern int omap_dispc_request_irq(void (*callback)(void *data), void *data); 40extern int omap_dispc_request_irq(unsigned long irq_mask,
41extern void omap_dispc_free_irq(void); 41 void (*callback)(void *data), void *data);
42extern void omap_dispc_free_irq(unsigned long irq_mask,
43 void (*callback)(void *data), void *data);
42 44
43extern const struct lcd_ctrl omap2_int_ctrl; 45extern const struct lcd_ctrl omap2_int_ctrl;
44
45#endif 46#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 5d4f34887a22..ca51583ec98a 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -131,7 +131,7 @@ struct {
131 131
132 struct omapfb_device *fbdev; 132 struct omapfb_device *fbdev;
133 struct lcd_ctrl_extif *extif; 133 struct lcd_ctrl_extif *extif;
134 struct lcd_ctrl *int_ctrl; 134 const struct lcd_ctrl *int_ctrl;
135 135
136 struct clk *sys_ck; 136 struct clk *sys_ck;
137} hwa742; 137} hwa742;
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c
new file mode 100644
index 000000000000..393712b6f369
--- /dev/null
+++ b/drivers/video/omap/lcd_2430sdp.c
@@ -0,0 +1,202 @@
1/*
2 * LCD panel support for the TI 2430SDP board
3 *
4 * Copyright (C) 2007 MontaVista
5 * Author: Hunyue Yau <hyau@mvista.com>
6 *
7 * Derived from drivers/video/omap/lcd-apollon.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/gpio.h>
28#include <linux/i2c/twl4030.h>
29
30#include <mach/mux.h>
31#include <mach/omapfb.h>
32#include <asm/mach-types.h>
33
34#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
35#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
36#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
37#define SDP3430_LCD_PANEL_ENABLE_GPIO 28
38
39static unsigned backlight_gpio;
40static unsigned enable_gpio;
41
42#define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */
43#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
44#define ENABLE_VAUX2_DEDICATED 0x09
45#define ENABLE_VAUX2_DEV_GRP 0x20
46#define ENABLE_VAUX3_DEDICATED 0x03
47#define ENABLE_VAUX3_DEV_GRP 0x20
48
49#define ENABLE_VPLL2_DEDICATED 0x05
50#define ENABLE_VPLL2_DEV_GRP 0xE0
51#define TWL4030_VPLL2_DEV_GRP 0x33
52#define TWL4030_VPLL2_DEDICATED 0x36
53
54#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
55
56
57static int sdp2430_panel_init(struct lcd_panel *panel,
58 struct omapfb_device *fbdev)
59{
60 if (machine_is_omap_3430sdp()) {
61 enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
62 backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
63 } else {
64 enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO;
65 backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO;
66 }
67
68 gpio_request(enable_gpio, "LCD enable"); /* LCD panel */
69 gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */
70 gpio_direction_output(enable_gpio, 0);
71 gpio_direction_output(backlight_gpio, 0);
72
73 return 0;
74}
75
76static void sdp2430_panel_cleanup(struct lcd_panel *panel)
77{
78 gpio_free(backlight_gpio);
79 gpio_free(enable_gpio);
80}
81
82static int sdp2430_panel_enable(struct lcd_panel *panel)
83{
84 u8 ded_val, ded_reg;
85 u8 grp_val, grp_reg;
86
87 if (machine_is_omap_3430sdp()) {
88 ded_reg = TWL4030_VAUX3_DEDICATED;
89 ded_val = ENABLE_VAUX3_DEDICATED;
90 grp_reg = TWL4030_VAUX3_DEV_GRP;
91 grp_val = ENABLE_VAUX3_DEV_GRP;
92
93 if (omap_rev() > OMAP3430_REV_ES1_0) {
94 t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
95 TWL4030_VPLL2_DEDICATED);
96 t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
97 TWL4030_VPLL2_DEV_GRP);
98 }
99 } else {
100 ded_reg = TWL4030_VAUX2_DEDICATED;
101 ded_val = ENABLE_VAUX2_DEDICATED;
102 grp_reg = TWL4030_VAUX2_DEV_GRP;
103 grp_val = ENABLE_VAUX2_DEV_GRP;
104 }
105
106 gpio_set_value(enable_gpio, 1);
107 gpio_set_value(backlight_gpio, 1);
108
109 if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
110 return -EIO;
111 if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
112 return -EIO;
113
114 return 0;
115}
116
117static void sdp2430_panel_disable(struct lcd_panel *panel)
118{
119 gpio_set_value(enable_gpio, 0);
120 gpio_set_value(backlight_gpio, 0);
121 if (omap_rev() > OMAP3430_REV_ES1_0) {
122 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
123 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
124 msleep(4);
125 }
126}
127
128static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel)
129{
130 return 0;
131}
132
133struct lcd_panel sdp2430_panel = {
134 .name = "sdp2430",
135 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
136 OMAP_LCDC_INV_HSYNC,
137
138 .bpp = 16,
139 .data_lines = 16,
140 .x_res = 240,
141 .y_res = 320,
142 .hsw = 3, /* hsync_len (4) - 1 */
143 .hfp = 3, /* right_margin (4) - 1 */
144 .hbp = 39, /* left_margin (40) - 1 */
145 .vsw = 1, /* vsync_len (2) - 1 */
146 .vfp = 2, /* lower_margin */
147 .vbp = 7, /* upper_margin (8) - 1 */
148
149 .pixel_clock = LCD_PIXCLOCK_MAX,
150
151 .init = sdp2430_panel_init,
152 .cleanup = sdp2430_panel_cleanup,
153 .enable = sdp2430_panel_enable,
154 .disable = sdp2430_panel_disable,
155 .get_caps = sdp2430_panel_get_caps,
156};
157
158static int sdp2430_panel_probe(struct platform_device *pdev)
159{
160 omapfb_register_panel(&sdp2430_panel);
161 return 0;
162}
163
164static int sdp2430_panel_remove(struct platform_device *pdev)
165{
166 return 0;
167}
168
169static int sdp2430_panel_suspend(struct platform_device *pdev,
170 pm_message_t mesg)
171{
172 return 0;
173}
174
175static int sdp2430_panel_resume(struct platform_device *pdev)
176{
177 return 0;
178}
179
180struct platform_driver sdp2430_panel_driver = {
181 .probe = sdp2430_panel_probe,
182 .remove = sdp2430_panel_remove,
183 .suspend = sdp2430_panel_suspend,
184 .resume = sdp2430_panel_resume,
185 .driver = {
186 .name = "sdp2430_lcd",
187 .owner = THIS_MODULE,
188 },
189};
190
191static int __init sdp2430_panel_drv_init(void)
192{
193 return platform_driver_register(&sdp2430_panel_driver);
194}
195
196static void __exit sdp2430_panel_drv_exit(void)
197{
198 platform_driver_unregister(&sdp2430_panel_driver);
199}
200
201module_init(sdp2430_panel_drv_init);
202module_exit(sdp2430_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
new file mode 100644
index 000000000000..1f7439955e02
--- /dev/null
+++ b/drivers/video/omap/lcd_ams_delta.c
@@ -0,0 +1,137 @@
1/*
2 * Based on drivers/video/omap/lcd_inn1510.c
3 *
4 * LCD panel support for the Amstrad E3 (Delta) videophone.
5 *
6 * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/io.h>
26#include <linux/delay.h>
27
28#include <mach/board-ams-delta.h>
29#include <mach/hardware.h>
30#include <mach/omapfb.h>
31
32#define AMS_DELTA_DEFAULT_CONTRAST 112
33
34static int ams_delta_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev)
36{
37 return 0;
38}
39
40static void ams_delta_panel_cleanup(struct lcd_panel *panel)
41{
42}
43
44static int ams_delta_panel_enable(struct lcd_panel *panel)
45{
46 ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP,
47 AMS_DELTA_LATCH2_LCD_NDISP);
48 ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN,
49 AMS_DELTA_LATCH2_LCD_VBLEN);
50
51 omap_writeb(1, OMAP_PWL_CLK_ENABLE);
52 omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE);
53
54 return 0;
55}
56
57static void ams_delta_panel_disable(struct lcd_panel *panel)
58{
59 ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, 0);
60 ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, 0);
61}
62
63static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel)
64{
65 return 0;
66}
67
68static struct lcd_panel ams_delta_panel = {
69 .name = "ams-delta",
70 .config = 0,
71
72 .bpp = 12,
73 .data_lines = 16,
74 .x_res = 480,
75 .y_res = 320,
76 .pixel_clock = 4687,
77 .hsw = 3,
78 .hfp = 1,
79 .hbp = 1,
80 .vsw = 1,
81 .vfp = 0,
82 .vbp = 0,
83 .pcd = 0,
84 .acb = 37,
85
86 .init = ams_delta_panel_init,
87 .cleanup = ams_delta_panel_cleanup,
88 .enable = ams_delta_panel_enable,
89 .disable = ams_delta_panel_disable,
90 .get_caps = ams_delta_panel_get_caps,
91};
92
93static int ams_delta_panel_probe(struct platform_device *pdev)
94{
95 omapfb_register_panel(&ams_delta_panel);
96 return 0;
97}
98
99static int ams_delta_panel_remove(struct platform_device *pdev)
100{
101 return 0;
102}
103
104static int ams_delta_panel_suspend(struct platform_device *pdev,
105 pm_message_t mesg)
106{
107 return 0;
108}
109
110static int ams_delta_panel_resume(struct platform_device *pdev)
111{
112 return 0;
113}
114
115struct platform_driver ams_delta_panel_driver = {
116 .probe = ams_delta_panel_probe,
117 .remove = ams_delta_panel_remove,
118 .suspend = ams_delta_panel_suspend,
119 .resume = ams_delta_panel_resume,
120 .driver = {
121 .name = "lcd_ams_delta",
122 .owner = THIS_MODULE,
123 },
124};
125
126static int ams_delta_panel_drv_init(void)
127{
128 return platform_driver_register(&ams_delta_panel_driver);
129}
130
131static void ams_delta_panel_drv_cleanup(void)
132{
133 platform_driver_unregister(&ams_delta_panel_driver);
134}
135
136module_init(ams_delta_panel_drv_init);
137module_exit(ams_delta_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c
new file mode 100644
index 000000000000..626ae3a532ff
--- /dev/null
+++ b/drivers/video/omap/lcd_apollon.c
@@ -0,0 +1,138 @@
1/*
2 * LCD panel support for the Samsung OMAP2 Apollon board
3 *
4 * Copyright (C) 2005,2006 Samsung Electronics
5 * Author: Kyungmin Park <kyungmin.park@samsung.com>
6 *
7 * Derived from drivers/video/omap/lcd-h4.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26
27#include <mach/gpio.h>
28#include <mach/mux.h>
29#include <mach/omapfb.h>
30
31/* #define USE_35INCH_LCD 1 */
32
33static int apollon_panel_init(struct lcd_panel *panel,
34 struct omapfb_device *fbdev)
35{
36 /* configure LCD PWR_EN */
37 omap_cfg_reg(M21_242X_GPIO11);
38 return 0;
39}
40
41static void apollon_panel_cleanup(struct lcd_panel *panel)
42{
43}
44
45static int apollon_panel_enable(struct lcd_panel *panel)
46{
47 return 0;
48}
49
50static void apollon_panel_disable(struct lcd_panel *panel)
51{
52}
53
54static unsigned long apollon_panel_get_caps(struct lcd_panel *panel)
55{
56 return 0;
57}
58
59struct lcd_panel apollon_panel = {
60 .name = "apollon",
61 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
62 OMAP_LCDC_INV_HSYNC,
63
64 .bpp = 16,
65 .data_lines = 18,
66#ifdef USE_35INCH_LCD
67 .x_res = 240,
68 .y_res = 320,
69 .hsw = 2,
70 .hfp = 3,
71 .hbp = 9,
72 .vsw = 4,
73 .vfp = 3,
74 .vbp = 5,
75#else
76 .x_res = 480,
77 .y_res = 272,
78 .hsw = 41,
79 .hfp = 2,
80 .hbp = 2,
81 .vsw = 10,
82 .vfp = 2,
83 .vbp = 2,
84#endif
85 .pixel_clock = 6250,
86
87 .init = apollon_panel_init,
88 .cleanup = apollon_panel_cleanup,
89 .enable = apollon_panel_enable,
90 .disable = apollon_panel_disable,
91 .get_caps = apollon_panel_get_caps,
92};
93
94static int apollon_panel_probe(struct platform_device *pdev)
95{
96 omapfb_register_panel(&apollon_panel);
97 return 0;
98}
99
100static int apollon_panel_remove(struct platform_device *pdev)
101{
102 return 0;
103}
104
105static int apollon_panel_suspend(struct platform_device *pdev,
106 pm_message_t mesg)
107{
108 return 0;
109}
110
111static int apollon_panel_resume(struct platform_device *pdev)
112{
113 return 0;
114}
115
116struct platform_driver apollon_panel_driver = {
117 .probe = apollon_panel_probe,
118 .remove = apollon_panel_remove,
119 .suspend = apollon_panel_suspend,
120 .resume = apollon_panel_resume,
121 .driver = {
122 .name = "apollon_lcd",
123 .owner = THIS_MODULE,
124 },
125};
126
127static int __init apollon_panel_drv_init(void)
128{
129 return platform_driver_register(&apollon_panel_driver);
130}
131
132static void __exit apollon_panel_drv_exit(void)
133{
134 platform_driver_unregister(&apollon_panel_driver);
135}
136
137module_init(apollon_panel_drv_init);
138module_exit(apollon_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 2486237ebba5..417ae5efa8bb 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -124,12 +124,12 @@ struct platform_driver h3_panel_driver = {
124 }, 124 },
125}; 125};
126 126
127static int h3_panel_drv_init(void) 127static int __init h3_panel_drv_init(void)
128{ 128{
129 return platform_driver_register(&h3_panel_driver); 129 return platform_driver_register(&h3_panel_driver);
130} 130}
131 131
132static void h3_panel_drv_cleanup(void) 132static void __exit h3_panel_drv_cleanup(void)
133{ 133{
134 platform_driver_unregister(&h3_panel_driver); 134 platform_driver_unregister(&h3_panel_driver);
135} 135}
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
index 6ff56430341b..0c398bda7601 100644
--- a/drivers/video/omap/lcd_h4.c
+++ b/drivers/video/omap/lcd_h4.c
@@ -102,12 +102,12 @@ static struct platform_driver h4_panel_driver = {
102 }, 102 },
103}; 103};
104 104
105static int h4_panel_drv_init(void) 105static int __init h4_panel_drv_init(void)
106{ 106{
107 return platform_driver_register(&h4_panel_driver); 107 return platform_driver_register(&h4_panel_driver);
108} 108}
109 109
110static void h4_panel_drv_cleanup(void) 110static void __exit h4_panel_drv_cleanup(void)
111{ 111{
112 platform_driver_unregister(&h4_panel_driver); 112 platform_driver_unregister(&h4_panel_driver);
113} 113}
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index 6953ed4b5820..cdbd8bb607be 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -109,12 +109,12 @@ struct platform_driver innovator1510_panel_driver = {
109 }, 109 },
110}; 110};
111 111
112static int innovator1510_panel_drv_init(void) 112static int __init innovator1510_panel_drv_init(void)
113{ 113{
114 return platform_driver_register(&innovator1510_panel_driver); 114 return platform_driver_register(&innovator1510_panel_driver);
115} 115}
116 116
117static void innovator1510_panel_drv_cleanup(void) 117static void __exit innovator1510_panel_drv_cleanup(void)
118{ 118{
119 platform_driver_unregister(&innovator1510_panel_driver); 119 platform_driver_unregister(&innovator1510_panel_driver);
120} 120}
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 4c4f7ee6d733..268f7f808a4e 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -133,12 +133,12 @@ struct platform_driver innovator1610_panel_driver = {
133 }, 133 },
134}; 134};
135 135
136static int innovator1610_panel_drv_init(void) 136static int __init innovator1610_panel_drv_init(void)
137{ 137{
138 return platform_driver_register(&innovator1610_panel_driver); 138 return platform_driver_register(&innovator1610_panel_driver);
139} 139}
140 140
141static void innovator1610_panel_drv_cleanup(void) 141static void __exit innovator1610_panel_drv_cleanup(void)
142{ 142{
143 platform_driver_unregister(&innovator1610_panel_driver); 143 platform_driver_unregister(&innovator1610_panel_driver);
144} 144}
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c
new file mode 100644
index 000000000000..dbfe8974fb94
--- /dev/null
+++ b/drivers/video/omap/lcd_ldp.c
@@ -0,0 +1,200 @@
1/*
2 * LCD panel support for the TI LDP board
3 *
4 * Copyright (C) 2007 WindRiver
5 * Author: Stanley Miao <stanley.miao@windriver.com>
6 *
7 * Derived from drivers/video/omap/lcd-2430sdp.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/i2c/twl4030.h>
28
29#include <mach/gpio.h>
30#include <mach/mux.h>
31#include <mach/omapfb.h>
32#include <asm/mach-types.h>
33
34#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
35#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES)
36
37#define LCD_PANEL_RESET_GPIO 55
38#define LCD_PANEL_QVGA_GPIO 56
39
40#ifdef CONFIG_FB_OMAP_LCD_VGA
41#define LCD_XRES 480
42#define LCD_YRES 640
43#define LCD_PIXCLOCK_MAX 41700
44#else
45#define LCD_XRES 240
46#define LCD_YRES 320
47#define LCD_PIXCLOCK_MAX 185186
48#endif
49
50#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
51#define ENABLE_VAUX2_DEDICATED 0x09
52#define ENABLE_VAUX2_DEV_GRP 0x20
53#define ENABLE_VAUX3_DEDICATED 0x03
54#define ENABLE_VAUX3_DEV_GRP 0x20
55
56#define ENABLE_VPLL2_DEDICATED 0x05
57#define ENABLE_VPLL2_DEV_GRP 0xE0
58#define TWL4030_VPLL2_DEV_GRP 0x33
59#define TWL4030_VPLL2_DEDICATED 0x36
60
61#define t2_out(c, r, v) twl4030_i2c_write_u8(c, r, v)
62
63
64static int ldp_panel_init(struct lcd_panel *panel,
65 struct omapfb_device *fbdev)
66{
67 gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset");
68 gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga");
69 gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel");
70 gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight");
71
72 gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0);
73 gpio_direction_output(LCD_PANEL_RESET_GPIO, 0);
74 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
75 gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
76
77#ifdef CONFIG_FB_OMAP_LCD_VGA
78 gpio_set_value(LCD_PANEL_QVGA_GPIO, 0);
79#else
80 gpio_set_value(LCD_PANEL_QVGA_GPIO, 1);
81#endif
82 gpio_set_value(LCD_PANEL_RESET_GPIO, 1);
83
84 return 0;
85}
86
87static void ldp_panel_cleanup(struct lcd_panel *panel)
88{
89 gpio_free(LCD_PANEL_BACKLIGHT_GPIO);
90 gpio_free(LCD_PANEL_ENABLE_GPIO);
91 gpio_free(LCD_PANEL_QVGA_GPIO);
92 gpio_free(LCD_PANEL_RESET_GPIO);
93}
94
95static int ldp_panel_enable(struct lcd_panel *panel)
96{
97 if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
98 TWL4030_VPLL2_DEDICATED))
99 return -EIO;
100 if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
101 TWL4030_VPLL2_DEV_GRP))
102 return -EIO;
103
104 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
105 gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1);
106
107 if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED,
108 TWL4030_VAUX3_DEDICATED))
109 return -EIO;
110 if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP,
111 TWL4030_VAUX3_DEV_GRP))
112 return -EIO;
113
114 return 0;
115}
116
117static void ldp_panel_disable(struct lcd_panel *panel)
118{
119 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
120 gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
121
122 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
123 t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
124 msleep(4);
125}
126
127static unsigned long ldp_panel_get_caps(struct lcd_panel *panel)
128{
129 return 0;
130}
131
132struct lcd_panel ldp_panel = {
133 .name = "ldp",
134 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
135 OMAP_LCDC_INV_HSYNC,
136
137 .bpp = 16,
138 .data_lines = 18,
139 .x_res = LCD_XRES,
140 .y_res = LCD_YRES,
141 .hsw = 3, /* hsync_len (4) - 1 */
142 .hfp = 3, /* right_margin (4) - 1 */
143 .hbp = 39, /* left_margin (40) - 1 */
144 .vsw = 1, /* vsync_len (2) - 1 */
145 .vfp = 2, /* lower_margin */
146 .vbp = 7, /* upper_margin (8) - 1 */
147
148 .pixel_clock = LCD_PIXCLOCK_MAX,
149
150 .init = ldp_panel_init,
151 .cleanup = ldp_panel_cleanup,
152 .enable = ldp_panel_enable,
153 .disable = ldp_panel_disable,
154 .get_caps = ldp_panel_get_caps,
155};
156
157static int ldp_panel_probe(struct platform_device *pdev)
158{
159 omapfb_register_panel(&ldp_panel);
160 return 0;
161}
162
163static int ldp_panel_remove(struct platform_device *pdev)
164{
165 return 0;
166}
167
168static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
169{
170 return 0;
171}
172
173static int ldp_panel_resume(struct platform_device *pdev)
174{
175 return 0;
176}
177
178struct platform_driver ldp_panel_driver = {
179 .probe = ldp_panel_probe,
180 .remove = ldp_panel_remove,
181 .suspend = ldp_panel_suspend,
182 .resume = ldp_panel_resume,
183 .driver = {
184 .name = "ldp_lcd",
185 .owner = THIS_MODULE,
186 },
187};
188
189static int __init ldp_panel_drv_init(void)
190{
191 return platform_driver_register(&ldp_panel_driver);
192}
193
194static void __exit ldp_panel_drv_exit(void)
195{
196 platform_driver_unregister(&ldp_panel_driver);
197}
198
199module_init(ldp_panel_drv_init);
200module_exit(ldp_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
new file mode 100644
index 000000000000..918ee8934196
--- /dev/null
+++ b/drivers/video/omap/lcd_mipid.c
@@ -0,0 +1,625 @@
1/*
2 * LCD driver for MIPI DBI-C / DCS compatible LCDs
3 *
4 * Copyright (C) 2006 Nokia Corporation
5 * Author: Imre Deak <imre.deak@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/device.h>
22#include <linux/delay.h>
23#include <linux/workqueue.h>
24#include <linux/spi/spi.h>
25
26#include <mach/omapfb.h>
27#include <mach/lcd_mipid.h>
28
29#define MIPID_MODULE_NAME "lcd_mipid"
30
31#define MIPID_CMD_READ_DISP_ID 0x04
32#define MIPID_CMD_READ_RED 0x06
33#define MIPID_CMD_READ_GREEN 0x07
34#define MIPID_CMD_READ_BLUE 0x08
35#define MIPID_CMD_READ_DISP_STATUS 0x09
36#define MIPID_CMD_RDDSDR 0x0F
37#define MIPID_CMD_SLEEP_IN 0x10
38#define MIPID_CMD_SLEEP_OUT 0x11
39#define MIPID_CMD_DISP_OFF 0x28
40#define MIPID_CMD_DISP_ON 0x29
41
42#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
43
44#define to_mipid_device(p) container_of(p, struct mipid_device, \
45 panel)
46struct mipid_device {
47 int enabled;
48 int revision;
49 unsigned int saved_bklight_level;
50 unsigned long hw_guard_end; /* next value of jiffies
51 when we can issue the
52 next sleep in/out command */
53 unsigned long hw_guard_wait; /* max guard time in jiffies */
54
55 struct omapfb_device *fbdev;
56 struct spi_device *spi;
57 struct mutex mutex;
58 struct lcd_panel panel;
59
60 struct workqueue_struct *esd_wq;
61 struct delayed_work esd_work;
62 void (*esd_check)(struct mipid_device *m);
63};
64
65static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
66 int wlen, u8 *rbuf, int rlen)
67{
68 struct spi_message m;
69 struct spi_transfer *x, xfer[4];
70 u16 w;
71 int r;
72
73 BUG_ON(md->spi == NULL);
74
75 spi_message_init(&m);
76
77 memset(xfer, 0, sizeof(xfer));
78 x = &xfer[0];
79
80 cmd &= 0xff;
81 x->tx_buf = &cmd;
82 x->bits_per_word = 9;
83 x->len = 2;
84 spi_message_add_tail(x, &m);
85
86 if (wlen) {
87 x++;
88 x->tx_buf = wbuf;
89 x->len = wlen;
90 x->bits_per_word = 9;
91 spi_message_add_tail(x, &m);
92 }
93
94 if (rlen) {
95 x++;
96 x->rx_buf = &w;
97 x->len = 1;
98 spi_message_add_tail(x, &m);
99
100 if (rlen > 1) {
101 /* Arrange for the extra clock before the first
102 * data bit.
103 */
104 x->bits_per_word = 9;
105 x->len = 2;
106
107 x++;
108 x->rx_buf = &rbuf[1];
109 x->len = rlen - 1;
110 spi_message_add_tail(x, &m);
111 }
112 }
113
114 r = spi_sync(md->spi, &m);
115 if (r < 0)
116 dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
117
118 if (rlen)
119 rbuf[0] = w & 0xff;
120}
121
122static inline void mipid_cmd(struct mipid_device *md, int cmd)
123{
124 mipid_transfer(md, cmd, NULL, 0, NULL, 0);
125}
126
127static inline void mipid_write(struct mipid_device *md,
128 int reg, const u8 *buf, int len)
129{
130 mipid_transfer(md, reg, buf, len, NULL, 0);
131}
132
133static inline void mipid_read(struct mipid_device *md,
134 int reg, u8 *buf, int len)
135{
136 mipid_transfer(md, reg, NULL, 0, buf, len);
137}
138
139static void set_data_lines(struct mipid_device *md, int data_lines)
140{
141 u16 par;
142
143 switch (data_lines) {
144 case 16:
145 par = 0x150;
146 break;
147 case 18:
148 par = 0x160;
149 break;
150 case 24:
151 par = 0x170;
152 break;
153 }
154 mipid_write(md, 0x3a, (u8 *)&par, 2);
155}
156
157static void send_init_string(struct mipid_device *md)
158{
159 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
160
161 mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
162 set_data_lines(md, md->panel.data_lines);
163}
164
165static void hw_guard_start(struct mipid_device *md, int guard_msec)
166{
167 md->hw_guard_wait = msecs_to_jiffies(guard_msec);
168 md->hw_guard_end = jiffies + md->hw_guard_wait;
169}
170
171static void hw_guard_wait(struct mipid_device *md)
172{
173 unsigned long wait = md->hw_guard_end - jiffies;
174
175 if ((long)wait > 0 && wait <= md->hw_guard_wait) {
176 set_current_state(TASK_UNINTERRUPTIBLE);
177 schedule_timeout(wait);
178 }
179}
180
181static void set_sleep_mode(struct mipid_device *md, int on)
182{
183 int cmd, sleep_time = 50;
184
185 if (on)
186 cmd = MIPID_CMD_SLEEP_IN;
187 else
188 cmd = MIPID_CMD_SLEEP_OUT;
189 hw_guard_wait(md);
190 mipid_cmd(md, cmd);
191 hw_guard_start(md, 120);
192 /*
193 * When we enable the panel, it seems we _have_ to sleep
194 * 120 ms before sending the init string. When disabling the
195 * panel we'll sleep for the duration of 2 frames, so that the
196 * controller can still provide the PCLK,HS,VS signals.
197 */
198 if (!on)
199 sleep_time = 120;
200 msleep(sleep_time);
201}
202
203static void set_display_state(struct mipid_device *md, int enabled)
204{
205 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
206
207 mipid_cmd(md, cmd);
208}
209
210static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
211{
212 struct mipid_device *md = to_mipid_device(panel);
213 struct mipid_platform_data *pd = md->spi->dev.platform_data;
214
215 if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL)
216 return -ENODEV;
217 if (level > pd->get_bklight_max(pd))
218 return -EINVAL;
219 if (!md->enabled) {
220 md->saved_bklight_level = level;
221 return 0;
222 }
223 pd->set_bklight_level(pd, level);
224
225 return 0;
226}
227
228static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
229{
230 struct mipid_device *md = to_mipid_device(panel);
231 struct mipid_platform_data *pd = md->spi->dev.platform_data;
232
233 if (pd->get_bklight_level == NULL)
234 return -ENODEV;
235 return pd->get_bklight_level(pd);
236}
237
238static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
239{
240 struct mipid_device *md = to_mipid_device(panel);
241 struct mipid_platform_data *pd = md->spi->dev.platform_data;
242
243 if (pd->get_bklight_max == NULL)
244 return -ENODEV;
245
246 return pd->get_bklight_max(pd);
247}
248
249static unsigned long mipid_get_caps(struct lcd_panel *panel)
250{
251 return OMAPFB_CAPS_SET_BACKLIGHT;
252}
253
254static u16 read_first_pixel(struct mipid_device *md)
255{
256 u16 pixel;
257 u8 red, green, blue;
258
259 mutex_lock(&md->mutex);
260 mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
261 mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
262 mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
263 mutex_unlock(&md->mutex);
264
265 switch (md->panel.data_lines) {
266 case 16:
267 pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
268 break;
269 case 24:
270 /* 24 bit -> 16 bit */
271 pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
272 (blue >> 3);
273 break;
274 default:
275 pixel = 0;
276 BUG();
277 }
278
279 return pixel;
280}
281
282static int mipid_run_test(struct lcd_panel *panel, int test_num)
283{
284 struct mipid_device *md = to_mipid_device(panel);
285 static const u16 test_values[4] = {
286 0x0000, 0xffff, 0xaaaa, 0x5555,
287 };
288 int i;
289
290 if (test_num != MIPID_TEST_RGB_LINES)
291 return MIPID_TEST_INVALID;
292
293 for (i = 0; i < ARRAY_SIZE(test_values); i++) {
294 int delay;
295 unsigned long tmo;
296
297 omapfb_write_first_pixel(md->fbdev, test_values[i]);
298 tmo = jiffies + msecs_to_jiffies(100);
299 delay = 25;
300 while (1) {
301 u16 pixel;
302
303 msleep(delay);
304 pixel = read_first_pixel(md);
305 if (pixel == test_values[i])
306 break;
307 if (time_after(jiffies, tmo)) {
308 dev_err(&md->spi->dev,
309 "MIPI LCD RGB I/F test failed: "
310 "expecting %04x, got %04x\n",
311 test_values[i], pixel);
312 return MIPID_TEST_FAILED;
313 }
314 delay = 10;
315 }
316 }
317
318 return 0;
319}
320
321static void ls041y3_esd_recover(struct mipid_device *md)
322{
323 dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
324 set_sleep_mode(md, 1);
325 set_sleep_mode(md, 0);
326}
327
328static void ls041y3_esd_check_mode1(struct mipid_device *md)
329{
330 u8 state1, state2;
331
332 mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
333 set_sleep_mode(md, 0);
334 mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
335 dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
336 state1, state2);
337 /* Each sleep out command will trigger a self diagnostic and flip
338 * Bit6 if the test passes.
339 */
340 if (!((state1 ^ state2) & (1 << 6)))
341 ls041y3_esd_recover(md);
342}
343
344static void ls041y3_esd_check_mode2(struct mipid_device *md)
345{
346 int i;
347 u8 rbuf[2];
348 static const struct {
349 int cmd;
350 int wlen;
351 u16 wbuf[3];
352 } *rd, rd_ctrl[7] = {
353 { 0xb0, 4, { 0x0101, 0x01fe, } },
354 { 0xb1, 4, { 0x01de, 0x0121, } },
355 { 0xc2, 4, { 0x0100, 0x0100, } },
356 { 0xbd, 2, { 0x0100, } },
357 { 0xc2, 4, { 0x01fc, 0x0103, } },
358 { 0xb4, 0, },
359 { 0x00, 0, },
360 };
361
362 rd = rd_ctrl;
363 for (i = 0; i < 3; i++, rd++)
364 mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
365
366 udelay(10);
367 mipid_read(md, rd->cmd, rbuf, 2);
368 rd++;
369
370 for (i = 0; i < 3; i++, rd++) {
371 udelay(10);
372 mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
373 }
374
375 dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
376 if (rbuf[1] == 0x00)
377 ls041y3_esd_recover(md);
378}
379
380static void ls041y3_esd_check(struct mipid_device *md)
381{
382 ls041y3_esd_check_mode1(md);
383 if (md->revision >= 0x88)
384 ls041y3_esd_check_mode2(md);
385}
386
387static void mipid_esd_start_check(struct mipid_device *md)
388{
389 if (md->esd_check != NULL)
390 queue_delayed_work(md->esd_wq, &md->esd_work,
391 MIPID_ESD_CHECK_PERIOD);
392}
393
394static void mipid_esd_stop_check(struct mipid_device *md)
395{
396 if (md->esd_check != NULL)
397 cancel_rearming_delayed_workqueue(md->esd_wq, &md->esd_work);
398}
399
400static void mipid_esd_work(struct work_struct *work)
401{
402 struct mipid_device *md = container_of(work, struct mipid_device,
403 esd_work.work);
404
405 mutex_lock(&md->mutex);
406 md->esd_check(md);
407 mutex_unlock(&md->mutex);
408 mipid_esd_start_check(md);
409}
410
411static int mipid_enable(struct lcd_panel *panel)
412{
413 struct mipid_device *md = to_mipid_device(panel);
414
415 mutex_lock(&md->mutex);
416
417 if (md->enabled) {
418 mutex_unlock(&md->mutex);
419 return 0;
420 }
421 set_sleep_mode(md, 0);
422 md->enabled = 1;
423 send_init_string(md);
424 set_display_state(md, 1);
425 mipid_set_bklight_level(panel, md->saved_bklight_level);
426 mipid_esd_start_check(md);
427
428 mutex_unlock(&md->mutex);
429 return 0;
430}
431
432static void mipid_disable(struct lcd_panel *panel)
433{
434 struct mipid_device *md = to_mipid_device(panel);
435
436 /*
437 * A final ESD work might be called before returning,
438 * so do this without holding the lock.
439 */
440 mipid_esd_stop_check(md);
441 mutex_lock(&md->mutex);
442
443 if (!md->enabled) {
444 mutex_unlock(&md->mutex);
445 return;
446 }
447 md->saved_bklight_level = mipid_get_bklight_level(panel);
448 mipid_set_bklight_level(panel, 0);
449 set_display_state(md, 0);
450 set_sleep_mode(md, 1);
451 md->enabled = 0;
452
453 mutex_unlock(&md->mutex);
454}
455
456static int panel_enabled(struct mipid_device *md)
457{
458 u32 disp_status;
459 int enabled;
460
461 mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
462 disp_status = __be32_to_cpu(disp_status);
463 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
464 dev_dbg(&md->spi->dev,
465 "LCD panel %senabled by bootloader (status 0x%04x)\n",
466 enabled ? "" : "not ", disp_status);
467 return enabled;
468}
469
470static int mipid_init(struct lcd_panel *panel,
471 struct omapfb_device *fbdev)
472{
473 struct mipid_device *md = to_mipid_device(panel);
474
475 md->fbdev = fbdev;
476 md->esd_wq = create_singlethread_workqueue("mipid_esd");
477 if (md->esd_wq == NULL) {
478 dev_err(&md->spi->dev, "can't create ESD workqueue\n");
479 return -ENOMEM;
480 }
481 INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
482 mutex_init(&md->mutex);
483
484 md->enabled = panel_enabled(md);
485
486 if (md->enabled)
487 mipid_esd_start_check(md);
488 else
489 md->saved_bklight_level = mipid_get_bklight_level(panel);
490
491 return 0;
492}
493
494static void mipid_cleanup(struct lcd_panel *panel)
495{
496 struct mipid_device *md = to_mipid_device(panel);
497
498 if (md->enabled)
499 mipid_esd_stop_check(md);
500 destroy_workqueue(md->esd_wq);
501}
502
503static struct lcd_panel mipid_panel = {
504 .config = OMAP_LCDC_PANEL_TFT,
505
506 .bpp = 16,
507 .x_res = 800,
508 .y_res = 480,
509 .pixel_clock = 21940,
510 .hsw = 50,
511 .hfp = 20,
512 .hbp = 15,
513 .vsw = 2,
514 .vfp = 1,
515 .vbp = 3,
516
517 .init = mipid_init,
518 .cleanup = mipid_cleanup,
519 .enable = mipid_enable,
520 .disable = mipid_disable,
521 .get_caps = mipid_get_caps,
522 .set_bklight_level = mipid_set_bklight_level,
523 .get_bklight_level = mipid_get_bklight_level,
524 .get_bklight_max = mipid_get_bklight_max,
525 .run_test = mipid_run_test,
526};
527
528static int mipid_detect(struct mipid_device *md)
529{
530 struct mipid_platform_data *pdata;
531 u8 display_id[3];
532
533 pdata = md->spi->dev.platform_data;
534 if (pdata == NULL) {
535 dev_err(&md->spi->dev, "missing platform data\n");
536 return -ENOENT;
537 }
538
539 mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3);
540 dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
541 display_id[0], display_id[1], display_id[2]);
542
543 switch (display_id[0]) {
544 case 0x45:
545 md->panel.name = "lph8923";
546 break;
547 case 0x83:
548 md->panel.name = "ls041y3";
549 md->esd_check = ls041y3_esd_check;
550 break;
551 default:
552 md->panel.name = "unknown";
553 dev_err(&md->spi->dev, "invalid display ID\n");
554 return -ENODEV;
555 }
556
557 md->revision = display_id[1];
558 md->panel.data_lines = pdata->data_lines;
559 pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n",
560 md->panel.name, md->revision, md->panel.data_lines);
561
562 return 0;
563}
564
565static int mipid_spi_probe(struct spi_device *spi)
566{
567 struct mipid_device *md;
568 int r;
569
570 md = kzalloc(sizeof(*md), GFP_KERNEL);
571 if (md == NULL) {
572 dev_err(&spi->dev, "out of memory\n");
573 return -ENOMEM;
574 }
575
576 spi->mode = SPI_MODE_0;
577 md->spi = spi;
578 dev_set_drvdata(&spi->dev, md);
579 md->panel = mipid_panel;
580
581 r = mipid_detect(md);
582 if (r < 0)
583 return r;
584
585 omapfb_register_panel(&md->panel);
586
587 return 0;
588}
589
590static int mipid_spi_remove(struct spi_device *spi)
591{
592 struct mipid_device *md = dev_get_drvdata(&spi->dev);
593
594 mipid_disable(&md->panel);
595 kfree(md);
596
597 return 0;
598}
599
600static struct spi_driver mipid_spi_driver = {
601 .driver = {
602 .name = MIPID_MODULE_NAME,
603 .bus = &spi_bus_type,
604 .owner = THIS_MODULE,
605 },
606 .probe = mipid_spi_probe,
607 .remove = __devexit_p(mipid_spi_remove),
608};
609
610static int mipid_drv_init(void)
611{
612 spi_register_driver(&mipid_spi_driver);
613
614 return 0;
615}
616module_init(mipid_drv_init);
617
618static void mipid_drv_cleanup(void)
619{
620 spi_unregister_driver(&mipid_spi_driver);
621}
622module_exit(mipid_drv_cleanup);
623
624MODULE_DESCRIPTION("MIPI display driver");
625MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c
new file mode 100644
index 000000000000..7a2bbe2ecec3
--- /dev/null
+++ b/drivers/video/omap/lcd_omap2evm.c
@@ -0,0 +1,191 @@
1/*
2 * LCD panel support for the MISTRAL OMAP2EVM board
3 *
4 * Author: Arun C <arunedarath@mistralsolutions.com>
5 *
6 * Derived from drivers/video/omap/lcd_omap3evm.c
7 * Derived from drivers/video/omap/lcd-apollon.c
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/gpio.h>
27#include <linux/i2c/twl4030.h>
28
29#include <mach/mux.h>
30#include <mach/omapfb.h>
31#include <asm/mach-types.h>
32
33#define LCD_PANEL_ENABLE_GPIO 154
34#define LCD_PANEL_LR 128
35#define LCD_PANEL_UD 129
36#define LCD_PANEL_INI 152
37#define LCD_PANEL_QVGA 148
38#define LCD_PANEL_RESB 153
39
40#define TWL_LED_LEDEN 0x00
41#define TWL_PWMA_PWMAON 0x00
42#define TWL_PWMA_PWMAOFF 0x01
43
44static unsigned int bklight_level;
45
46static int omap2evm_panel_init(struct lcd_panel *panel,
47 struct omapfb_device *fbdev)
48{
49 gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable");
50 gpio_request(LCD_PANEL_LR, "LCD lr");
51 gpio_request(LCD_PANEL_UD, "LCD ud");
52 gpio_request(LCD_PANEL_INI, "LCD ini");
53 gpio_request(LCD_PANEL_QVGA, "LCD qvga");
54 gpio_request(LCD_PANEL_RESB, "LCD resb");
55
56 gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
57 gpio_direction_output(LCD_PANEL_RESB, 1);
58 gpio_direction_output(LCD_PANEL_INI, 1);
59 gpio_direction_output(LCD_PANEL_QVGA, 0);
60 gpio_direction_output(LCD_PANEL_LR, 1);
61 gpio_direction_output(LCD_PANEL_UD, 1);
62
63 twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
64 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
65 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
66 bklight_level = 100;
67
68 return 0;
69}
70
71static void omap2evm_panel_cleanup(struct lcd_panel *panel)
72{
73 gpio_free(LCD_PANEL_RESB);
74 gpio_free(LCD_PANEL_QVGA);
75 gpio_free(LCD_PANEL_INI);
76 gpio_free(LCD_PANEL_UD);
77 gpio_free(LCD_PANEL_LR);
78 gpio_free(LCD_PANEL_ENABLE_GPIO);
79}
80
81static int omap2evm_panel_enable(struct lcd_panel *panel)
82{
83 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
84 return 0;
85}
86
87static void omap2evm_panel_disable(struct lcd_panel *panel)
88{
89 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
90}
91
92static unsigned long omap2evm_panel_get_caps(struct lcd_panel *panel)
93{
94 return 0;
95}
96
97static int omap2evm_bklight_setlevel(struct lcd_panel *panel,
98 unsigned int level)
99{
100 u8 c;
101 if ((level >= 0) && (level <= 100)) {
102 c = (125 * (100 - level)) / 100 + 2;
103 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
104 bklight_level = level;
105 }
106 return 0;
107}
108
109static unsigned int omap2evm_bklight_getlevel(struct lcd_panel *panel)
110{
111 return bklight_level;
112}
113
114static unsigned int omap2evm_bklight_getmaxlevel(struct lcd_panel *panel)
115{
116 return 100;
117}
118
119struct lcd_panel omap2evm_panel = {
120 .name = "omap2evm",
121 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
122 OMAP_LCDC_INV_HSYNC,
123
124 .bpp = 16,
125 .data_lines = 18,
126 .x_res = 480,
127 .y_res = 640,
128 .hsw = 3,
129 .hfp = 0,
130 .hbp = 28,
131 .vsw = 2,
132 .vfp = 1,
133 .vbp = 0,
134
135 .pixel_clock = 20000,
136
137 .init = omap2evm_panel_init,
138 .cleanup = omap2evm_panel_cleanup,
139 .enable = omap2evm_panel_enable,
140 .disable = omap2evm_panel_disable,
141 .get_caps = omap2evm_panel_get_caps,
142 .set_bklight_level = omap2evm_bklight_setlevel,
143 .get_bklight_level = omap2evm_bklight_getlevel,
144 .get_bklight_max = omap2evm_bklight_getmaxlevel,
145};
146
147static int omap2evm_panel_probe(struct platform_device *pdev)
148{
149 omapfb_register_panel(&omap2evm_panel);
150 return 0;
151}
152
153static int omap2evm_panel_remove(struct platform_device *pdev)
154{
155 return 0;
156}
157
158static int omap2evm_panel_suspend(struct platform_device *pdev,
159 pm_message_t mesg)
160{
161 return 0;
162}
163
164static int omap2evm_panel_resume(struct platform_device *pdev)
165{
166 return 0;
167}
168
169struct platform_driver omap2evm_panel_driver = {
170 .probe = omap2evm_panel_probe,
171 .remove = omap2evm_panel_remove,
172 .suspend = omap2evm_panel_suspend,
173 .resume = omap2evm_panel_resume,
174 .driver = {
175 .name = "omap2evm_lcd",
176 .owner = THIS_MODULE,
177 },
178};
179
180static int __init omap2evm_panel_drv_init(void)
181{
182 return platform_driver_register(&omap2evm_panel_driver);
183}
184
185static void __exit omap2evm_panel_drv_exit(void)
186{
187 platform_driver_unregister(&omap2evm_panel_driver);
188}
189
190module_init(omap2evm_panel_drv_init);
191module_exit(omap2evm_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c
new file mode 100644
index 000000000000..4011910123bf
--- /dev/null
+++ b/drivers/video/omap/lcd_omap3beagle.c
@@ -0,0 +1,130 @@
1/*
2 * LCD panel support for the TI OMAP3 Beagle board
3 *
4 * Author: Koen Kooi <koen@openembedded.org>
5 *
6 * Derived from drivers/video/omap/lcd-omap3evm.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/gpio.h>
26#include <linux/i2c/twl4030.h>
27
28#include <mach/mux.h>
29#include <mach/omapfb.h>
30#include <asm/mach-types.h>
31
32#define LCD_PANEL_ENABLE_GPIO 170
33
34static int omap3beagle_panel_init(struct lcd_panel *panel,
35 struct omapfb_device *fbdev)
36{
37 gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable");
38 return 0;
39}
40
41static void omap3beagle_panel_cleanup(struct lcd_panel *panel)
42{
43 gpio_free(LCD_PANEL_ENABLE_GPIO);
44}
45
46static int omap3beagle_panel_enable(struct lcd_panel *panel)
47{
48 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
49 return 0;
50}
51
52static void omap3beagle_panel_disable(struct lcd_panel *panel)
53{
54 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
55}
56
57static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel)
58{
59 return 0;
60}
61
62struct lcd_panel omap3beagle_panel = {
63 .name = "omap3beagle",
64 .config = OMAP_LCDC_PANEL_TFT,
65
66 .bpp = 16,
67 .data_lines = 24,
68 .x_res = 1024,
69 .y_res = 768,
70 .hsw = 3, /* hsync_len (4) - 1 */
71 .hfp = 3, /* right_margin (4) - 1 */
72 .hbp = 39, /* left_margin (40) - 1 */
73 .vsw = 1, /* vsync_len (2) - 1 */
74 .vfp = 2, /* lower_margin */
75 .vbp = 7, /* upper_margin (8) - 1 */
76
77 .pixel_clock = 64000,
78
79 .init = omap3beagle_panel_init,
80 .cleanup = omap3beagle_panel_cleanup,
81 .enable = omap3beagle_panel_enable,
82 .disable = omap3beagle_panel_disable,
83 .get_caps = omap3beagle_panel_get_caps,
84};
85
86static int omap3beagle_panel_probe(struct platform_device *pdev)
87{
88 omapfb_register_panel(&omap3beagle_panel);
89 return 0;
90}
91
92static int omap3beagle_panel_remove(struct platform_device *pdev)
93{
94 return 0;
95}
96
97static int omap3beagle_panel_suspend(struct platform_device *pdev,
98 pm_message_t mesg)
99{
100 return 0;
101}
102
103static int omap3beagle_panel_resume(struct platform_device *pdev)
104{
105 return 0;
106}
107
108struct platform_driver omap3beagle_panel_driver = {
109 .probe = omap3beagle_panel_probe,
110 .remove = omap3beagle_panel_remove,
111 .suspend = omap3beagle_panel_suspend,
112 .resume = omap3beagle_panel_resume,
113 .driver = {
114 .name = "omap3beagle_lcd",
115 .owner = THIS_MODULE,
116 },
117};
118
119static int __init omap3beagle_panel_drv_init(void)
120{
121 return platform_driver_register(&omap3beagle_panel_driver);
122}
123
124static void __exit omap3beagle_panel_drv_exit(void)
125{
126 platform_driver_unregister(&omap3beagle_panel_driver);
127}
128
129module_init(omap3beagle_panel_drv_init);
130module_exit(omap3beagle_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c
new file mode 100644
index 000000000000..b6a4c2c57a2f
--- /dev/null
+++ b/drivers/video/omap/lcd_omap3evm.c
@@ -0,0 +1,192 @@
1/*
2 * LCD panel support for the TI OMAP3 EVM board
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * Derived from drivers/video/omap/lcd-apollon.c
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/gpio.h>
26#include <linux/i2c/twl4030.h>
27
28#include <mach/mux.h>
29#include <mach/omapfb.h>
30#include <asm/mach-types.h>
31
32#define LCD_PANEL_ENABLE_GPIO 153
33#define LCD_PANEL_LR 2
34#define LCD_PANEL_UD 3
35#define LCD_PANEL_INI 152
36#define LCD_PANEL_QVGA 154
37#define LCD_PANEL_RESB 155
38
39#define ENABLE_VDAC_DEDICATED 0x03
40#define ENABLE_VDAC_DEV_GRP 0x20
41#define ENABLE_VPLL2_DEDICATED 0x05
42#define ENABLE_VPLL2_DEV_GRP 0xE0
43
44#define TWL_LED_LEDEN 0x00
45#define TWL_PWMA_PWMAON 0x00
46#define TWL_PWMA_PWMAOFF 0x01
47
48static unsigned int bklight_level;
49
50static int omap3evm_panel_init(struct lcd_panel *panel,
51 struct omapfb_device *fbdev)
52{
53 gpio_request(LCD_PANEL_LR, "LCD lr");
54 gpio_request(LCD_PANEL_UD, "LCD ud");
55 gpio_request(LCD_PANEL_INI, "LCD ini");
56 gpio_request(LCD_PANEL_RESB, "LCD resb");
57 gpio_request(LCD_PANEL_QVGA, "LCD qvga");
58
59 gpio_direction_output(LCD_PANEL_RESB, 1);
60 gpio_direction_output(LCD_PANEL_INI, 1);
61 gpio_direction_output(LCD_PANEL_QVGA, 0);
62 gpio_direction_output(LCD_PANEL_LR, 1);
63 gpio_direction_output(LCD_PANEL_UD, 1);
64
65 twl4030_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
66 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
67 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
68 bklight_level = 100;
69
70 return 0;
71}
72
73static void omap3evm_panel_cleanup(struct lcd_panel *panel)
74{
75 gpio_free(LCD_PANEL_QVGA);
76 gpio_free(LCD_PANEL_RESB);
77 gpio_free(LCD_PANEL_INI);
78 gpio_free(LCD_PANEL_UD);
79 gpio_free(LCD_PANEL_LR);
80}
81
82static int omap3evm_panel_enable(struct lcd_panel *panel)
83{
84 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
85 return 0;
86}
87
88static void omap3evm_panel_disable(struct lcd_panel *panel)
89{
90 gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
91}
92
93static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
94{
95 return 0;
96}
97
98static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
99 unsigned int level)
100{
101 u8 c;
102 if ((level >= 0) && (level <= 100)) {
103 c = (125 * (100 - level)) / 100 + 2;
104 twl4030_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
105 bklight_level = level;
106 }
107 return 0;
108}
109
110static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)
111{
112 return bklight_level;
113}
114
115static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel)
116{
117 return 100;
118}
119
120struct lcd_panel omap3evm_panel = {
121 .name = "omap3evm",
122 .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
123 OMAP_LCDC_INV_HSYNC,
124
125 .bpp = 16,
126 .data_lines = 18,
127 .x_res = 480,
128 .y_res = 640,
129 .hsw = 3, /* hsync_len (4) - 1 */
130 .hfp = 3, /* right_margin (4) - 1 */
131 .hbp = 39, /* left_margin (40) - 1 */
132 .vsw = 1, /* vsync_len (2) - 1 */
133 .vfp = 2, /* lower_margin */
134 .vbp = 7, /* upper_margin (8) - 1 */
135
136 .pixel_clock = 26000,
137
138 .init = omap3evm_panel_init,
139 .cleanup = omap3evm_panel_cleanup,
140 .enable = omap3evm_panel_enable,
141 .disable = omap3evm_panel_disable,
142 .get_caps = omap3evm_panel_get_caps,
143 .set_bklight_level = omap3evm_bklight_setlevel,
144 .get_bklight_level = omap3evm_bklight_getlevel,
145 .get_bklight_max = omap3evm_bklight_getmaxlevel,
146};
147
148static int omap3evm_panel_probe(struct platform_device *pdev)
149{
150 omapfb_register_panel(&omap3evm_panel);
151 return 0;
152}
153
154static int omap3evm_panel_remove(struct platform_device *pdev)
155{
156 return 0;
157}
158
159static int omap3evm_panel_suspend(struct platform_device *pdev,
160 pm_message_t mesg)
161{
162 return 0;
163}
164
165static int omap3evm_panel_resume(struct platform_device *pdev)
166{
167 return 0;
168}
169
170struct platform_driver omap3evm_panel_driver = {
171 .probe = omap3evm_panel_probe,
172 .remove = omap3evm_panel_remove,
173 .suspend = omap3evm_panel_suspend,
174 .resume = omap3evm_panel_resume,
175 .driver = {
176 .name = "omap3evm_lcd",
177 .owner = THIS_MODULE,
178 },
179};
180
181static int __init omap3evm_panel_drv_init(void)
182{
183 return platform_driver_register(&omap3evm_panel_driver);
184}
185
186static void __exit omap3evm_panel_drv_exit(void)
187{
188 platform_driver_unregister(&omap3evm_panel_driver);
189}
190
191module_init(omap3evm_panel_drv_init);
192module_exit(omap3evm_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index 379c96d36da5..b3fa88bc6269 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -127,12 +127,12 @@ struct platform_driver osk_panel_driver = {
127 }, 127 },
128}; 128};
129 129
130static int osk_panel_drv_init(void) 130static int __init osk_panel_drv_init(void)
131{ 131{
132 return platform_driver_register(&osk_panel_driver); 132 return platform_driver_register(&osk_panel_driver);
133} 133}
134 134
135static void osk_panel_drv_cleanup(void) 135static void __exit osk_panel_drv_cleanup(void)
136{ 136{
137 platform_driver_unregister(&osk_panel_driver); 137 platform_driver_unregister(&osk_panel_driver);
138} 138}
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c
new file mode 100644
index 000000000000..2bc5c9268e5e
--- /dev/null
+++ b/drivers/video/omap/lcd_overo.c
@@ -0,0 +1,179 @@
1/*
2 * LCD panel support for the Gumstix Overo
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/i2c/twl4030.h>
25
26#include <mach/gpio.h>
27#include <mach/mux.h>
28#include <mach/omapfb.h>
29#include <asm/mach-types.h>
30
31#define LCD_ENABLE 144
32
33static int overo_panel_init(struct lcd_panel *panel,
34 struct omapfb_device *fbdev)
35{
36 if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) &&
37 (gpio_direction_output(LCD_ENABLE, 1) == 0))
38 gpio_export(LCD_ENABLE, 0);
39 else
40 printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n");
41
42 return 0;
43}
44
45static void overo_panel_cleanup(struct lcd_panel *panel)
46{
47 gpio_free(LCD_ENABLE);
48}
49
50static int overo_panel_enable(struct lcd_panel *panel)
51{
52 gpio_set_value(LCD_ENABLE, 1);
53 return 0;
54}
55
56static void overo_panel_disable(struct lcd_panel *panel)
57{
58 gpio_set_value(LCD_ENABLE, 0);
59}
60
61static unsigned long overo_panel_get_caps(struct lcd_panel *panel)
62{
63 return 0;
64}
65
66struct lcd_panel overo_panel = {
67 .name = "overo",
68 .config = OMAP_LCDC_PANEL_TFT,
69 .bpp = 16,
70 .data_lines = 24,
71
72#if defined CONFIG_FB_OMAP_031M3R
73
74 /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
75 .x_res = 640,
76 .y_res = 480,
77 .hfp = 48,
78 .hsw = 32,
79 .hbp = 80,
80 .vfp = 3,
81 .vsw = 4,
82 .vbp = 7,
83 .pixel_clock = 23500,
84
85#elif defined CONFIG_FB_OMAP_048M3R
86
87 /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */
88 .x_res = 800,
89 .y_res = 600,
90 .hfp = 48,
91 .hsw = 32,
92 .hbp = 80,
93 .vfp = 3,
94 .vsw = 4,
95 .vbp = 11,
96 .pixel_clock = 35500,
97
98#elif defined CONFIG_FB_OMAP_079M3R
99
100 /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
101 .x_res = 1024,
102 .y_res = 768,
103 .hfp = 48,
104 .hsw = 32,
105 .hbp = 80,
106 .vfp = 3,
107 .vsw = 4,
108 .vbp = 15,
109 .pixel_clock = 56000,
110
111#elif defined CONFIG_FB_OMAP_092M9R
112
113 /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
114 .x_res = 1280,
115 .y_res = 720,
116 .hfp = 48,
117 .hsw = 32,
118 .hbp = 80,
119 .vfp = 3,
120 .vsw = 5,
121 .vbp = 13,
122 .pixel_clock = 64000,
123
124#else
125
126 /* use 640 x 480 if no config option */
127 /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
128 .x_res = 640,
129 .y_res = 480,
130 .hfp = 48,
131 .hsw = 32,
132 .hbp = 80,
133 .vfp = 3,
134 .vsw = 4,
135 .vbp = 7,
136 .pixel_clock = 23500,
137
138#endif
139
140 .init = overo_panel_init,
141 .cleanup = overo_panel_cleanup,
142 .enable = overo_panel_enable,
143 .disable = overo_panel_disable,
144 .get_caps = overo_panel_get_caps,
145};
146
147static int overo_panel_probe(struct platform_device *pdev)
148{
149 omapfb_register_panel(&overo_panel);
150 return 0;
151}
152
153static int overo_panel_remove(struct platform_device *pdev)
154{
155 /* omapfb does not have unregister_panel */
156 return 0;
157}
158
159static struct platform_driver overo_panel_driver = {
160 .probe = overo_panel_probe,
161 .remove = overo_panel_remove,
162 .driver = {
163 .name = "overo_lcd",
164 .owner = THIS_MODULE,
165 },
166};
167
168static int __init overo_panel_drv_init(void)
169{
170 return platform_driver_register(&overo_panel_driver);
171}
172
173static void __exit overo_panel_drv_exit(void)
174{
175 platform_driver_unregister(&overo_panel_driver);
176}
177
178module_init(overo_panel_drv_init);
179module_exit(overo_panel_drv_exit);
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 218317366e6e..4bf3c79f3cc7 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -108,12 +108,12 @@ struct platform_driver palmte_panel_driver = {
108 }, 108 },
109}; 109};
110 110
111static int palmte_panel_drv_init(void) 111static int __init palmte_panel_drv_init(void)
112{ 112{
113 return platform_driver_register(&palmte_panel_driver); 113 return platform_driver_register(&palmte_panel_driver);
114} 114}
115 115
116static void palmte_panel_drv_cleanup(void) 116static void __exit palmte_panel_drv_cleanup(void)
117{ 117{
118 platform_driver_unregister(&palmte_panel_driver); 118 platform_driver_unregister(&palmte_panel_driver);
119} 119}
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
index 57b0f6cf6a5a..48ea1f9f2cbf 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -113,12 +113,12 @@ struct platform_driver palmtt_panel_driver = {
113 }, 113 },
114}; 114};
115 115
116static int palmtt_panel_drv_init(void) 116static int __init palmtt_panel_drv_init(void)
117{ 117{
118 return platform_driver_register(&palmtt_panel_driver); 118 return platform_driver_register(&palmtt_panel_driver);
119} 119}
120 120
121static void palmtt_panel_drv_cleanup(void) 121static void __exit palmtt_panel_drv_cleanup(void)
122{ 122{
123 platform_driver_unregister(&palmtt_panel_driver); 123 platform_driver_unregister(&palmtt_panel_driver);
124} 124}
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
index d33d78b11723..0697d29b4d3b 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -109,12 +109,12 @@ struct platform_driver palmz71_panel_driver = {
109 }, 109 },
110}; 110};
111 111
112static int palmz71_panel_drv_init(void) 112static int __init palmz71_panel_drv_init(void)
113{ 113{
114 return platform_driver_register(&palmz71_panel_driver); 114 return platform_driver_register(&palmz71_panel_driver);
115} 115}
116 116
117static void palmz71_panel_drv_cleanup(void) 117static void __exit palmz71_panel_drv_cleanup(void)
118{ 118{
119 platform_driver_unregister(&palmz71_panel_driver); 119 platform_driver_unregister(&palmz71_panel_driver);
120} 120}
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 060d72fe57cb..0d0c8c8b9b56 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -67,6 +67,7 @@ static struct caps_table_struct ctrl_caps[] = {
67 { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" }, 67 { OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE, "pixel double window" },
68 { OMAPFB_CAPS_WINDOW_SCALE, "scale window" }, 68 { OMAPFB_CAPS_WINDOW_SCALE, "scale window" },
69 { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" }, 69 { OMAPFB_CAPS_WINDOW_OVERLAY, "overlay window" },
70 { OMAPFB_CAPS_WINDOW_ROTATE, "rotate window" },
70 { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" }, 71 { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" },
71}; 72};
72 73
@@ -215,6 +216,15 @@ static int ctrl_change_mode(struct fb_info *fbi)
215 offset, var->xres_virtual, 216 offset, var->xres_virtual,
216 plane->info.pos_x, plane->info.pos_y, 217 plane->info.pos_x, plane->info.pos_y,
217 var->xres, var->yres, plane->color_mode); 218 var->xres, var->yres, plane->color_mode);
219 if (r < 0)
220 return r;
221
222 if (fbdev->ctrl->set_rotate != NULL) {
223 r = fbdev->ctrl->set_rotate(var->rotate);
224 if (r < 0)
225 return r;
226 }
227
218 if (fbdev->ctrl->set_scale != NULL) 228 if (fbdev->ctrl->set_scale != NULL)
219 r = fbdev->ctrl->set_scale(plane->idx, 229 r = fbdev->ctrl->set_scale(plane->idx,
220 var->xres, var->yres, 230 var->xres, var->yres,
@@ -383,7 +393,7 @@ static void omapfb_sync(struct fb_info *fbi)
383 * Set fb_info.fix fields and also updates fbdev. 393 * Set fb_info.fix fields and also updates fbdev.
384 * When calling this fb_info.var must be set up already. 394 * When calling this fb_info.var must be set up already.
385 */ 395 */
386static void set_fb_fix(struct fb_info *fbi) 396static void set_fb_fix(struct fb_info *fbi, int from_init)
387{ 397{
388 struct fb_fix_screeninfo *fix = &fbi->fix; 398 struct fb_fix_screeninfo *fix = &fbi->fix;
389 struct fb_var_screeninfo *var = &fbi->var; 399 struct fb_var_screeninfo *var = &fbi->var;
@@ -393,8 +403,16 @@ static void set_fb_fix(struct fb_info *fbi)
393 403
394 rg = &plane->fbdev->mem_desc.region[plane->idx]; 404 rg = &plane->fbdev->mem_desc.region[plane->idx];
395 fbi->screen_base = rg->vaddr; 405 fbi->screen_base = rg->vaddr;
396 fix->smem_start = rg->paddr; 406
397 fix->smem_len = rg->size; 407 if (!from_init) {
408 mutex_lock(&fbi->mm_lock);
409 fix->smem_start = rg->paddr;
410 fix->smem_len = rg->size;
411 mutex_unlock(&fbi->mm_lock);
412 } else {
413 fix->smem_start = rg->paddr;
414 fix->smem_len = rg->size;
415 }
398 416
399 fix->type = FB_TYPE_PACKED_PIXELS; 417 fix->type = FB_TYPE_PACKED_PIXELS;
400 bpp = var->bits_per_pixel; 418 bpp = var->bits_per_pixel;
@@ -552,7 +570,6 @@ static int set_fb_var(struct fb_info *fbi,
552 var->xoffset = var->xres_virtual - var->xres; 570 var->xoffset = var->xres_virtual - var->xres;
553 if (var->yres + var->yoffset > var->yres_virtual) 571 if (var->yres + var->yoffset > var->yres_virtual)
554 var->yoffset = var->yres_virtual - var->yres; 572 var->yoffset = var->yres_virtual - var->yres;
555 line_size = var->xres * bpp / 8;
556 573
557 if (plane->color_mode == OMAPFB_COLOR_RGB444) { 574 if (plane->color_mode == OMAPFB_COLOR_RGB444) {
558 var->red.offset = 8; var->red.length = 4; 575 var->red.offset = 8; var->red.length = 4;
@@ -598,7 +615,7 @@ static void omapfb_rotate(struct fb_info *fbi, int rotate)
598 struct omapfb_device *fbdev = plane->fbdev; 615 struct omapfb_device *fbdev = plane->fbdev;
599 616
600 omapfb_rqueue_lock(fbdev); 617 omapfb_rqueue_lock(fbdev);
601 if (cpu_is_omap15xx() && rotate != fbi->var.rotate) { 618 if (rotate != fbi->var.rotate) {
602 struct fb_var_screeninfo *new_var = &fbdev->new_var; 619 struct fb_var_screeninfo *new_var = &fbdev->new_var;
603 620
604 memcpy(new_var, &fbi->var, sizeof(*new_var)); 621 memcpy(new_var, &fbi->var, sizeof(*new_var));
@@ -693,7 +710,7 @@ static int omapfb_set_par(struct fb_info *fbi)
693 int r = 0; 710 int r = 0;
694 711
695 omapfb_rqueue_lock(fbdev); 712 omapfb_rqueue_lock(fbdev);
696 set_fb_fix(fbi); 713 set_fb_fix(fbi, 0);
697 r = ctrl_change_mode(fbi); 714 r = ctrl_change_mode(fbi);
698 omapfb_rqueue_unlock(fbdev); 715 omapfb_rqueue_unlock(fbdev);
699 716
@@ -705,28 +722,42 @@ int omapfb_update_window_async(struct fb_info *fbi,
705 void (*callback)(void *), 722 void (*callback)(void *),
706 void *callback_data) 723 void *callback_data)
707{ 724{
725 int xres, yres;
708 struct omapfb_plane_struct *plane = fbi->par; 726 struct omapfb_plane_struct *plane = fbi->par;
709 struct omapfb_device *fbdev = plane->fbdev; 727 struct omapfb_device *fbdev = plane->fbdev;
710 struct fb_var_screeninfo *var; 728 struct fb_var_screeninfo *var = &fbi->var;
711 729
712 var = &fbi->var; 730 switch (var->rotate) {
713 if (win->x >= var->xres || win->y >= var->yres || 731 case 0:
714 win->out_x > var->xres || win->out_y >= var->yres) 732 case 180:
733 xres = fbdev->panel->x_res;
734 yres = fbdev->panel->y_res;
735 break;
736 case 90:
737 case 270:
738 xres = fbdev->panel->y_res;
739 yres = fbdev->panel->x_res;
740 break;
741 default:
742 return -EINVAL;
743 }
744
745 if (win->x >= xres || win->y >= yres ||
746 win->out_x > xres || win->out_y > yres)
715 return -EINVAL; 747 return -EINVAL;
716 748
717 if (!fbdev->ctrl->update_window || 749 if (!fbdev->ctrl->update_window ||
718 fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE) 750 fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
719 return -ENODEV; 751 return -ENODEV;
720 752
721 if (win->x + win->width >= var->xres) 753 if (win->x + win->width > xres)
722 win->width = var->xres - win->x; 754 win->width = xres - win->x;
723 if (win->y + win->height >= var->yres) 755 if (win->y + win->height > yres)
724 win->height = var->yres - win->y; 756 win->height = yres - win->y;
725 /* The out sizes should be cropped to the LCD size */ 757 if (win->out_x + win->out_width > xres)
726 if (win->out_x + win->out_width > fbdev->panel->x_res) 758 win->out_width = xres - win->out_x;
727 win->out_width = fbdev->panel->x_res - win->out_x; 759 if (win->out_y + win->out_height > yres)
728 if (win->out_y + win->out_height > fbdev->panel->y_res) 760 win->out_height = yres - win->out_y;
729 win->out_height = fbdev->panel->y_res - win->out_y;
730 if (!win->width || !win->height || !win->out_width || !win->out_height) 761 if (!win->width || !win->height || !win->out_width || !win->out_height)
731 return 0; 762 return 0;
732 763
@@ -879,15 +910,17 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
879 if (old_size != size) { 910 if (old_size != size) {
880 if (size) { 911 if (size) {
881 memcpy(&fbi->var, new_var, sizeof(fbi->var)); 912 memcpy(&fbi->var, new_var, sizeof(fbi->var));
882 set_fb_fix(fbi); 913 set_fb_fix(fbi, 0);
883 } else { 914 } else {
884 /* 915 /*
885 * Set these explicitly to indicate that the 916 * Set these explicitly to indicate that the
886 * plane memory is dealloce'd, the other 917 * plane memory is dealloce'd, the other
887 * screen parameters in var / fix are invalid. 918 * screen parameters in var / fix are invalid.
888 */ 919 */
920 mutex_lock(&fbi->mm_lock);
889 fbi->fix.smem_start = 0; 921 fbi->fix.smem_start = 0;
890 fbi->fix.smem_len = 0; 922 fbi->fix.smem_len = 0;
923 mutex_unlock(&fbi->mm_lock);
891 } 924 }
892 } 925 }
893 } 926 }
@@ -1250,7 +1283,7 @@ static struct fb_ops omapfb_ops = {
1250static ssize_t omapfb_show_caps_num(struct device *dev, 1283static ssize_t omapfb_show_caps_num(struct device *dev,
1251 struct device_attribute *attr, char *buf) 1284 struct device_attribute *attr, char *buf)
1252{ 1285{
1253 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1286 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1254 int plane; 1287 int plane;
1255 size_t size; 1288 size_t size;
1256 struct omapfb_caps caps; 1289 struct omapfb_caps caps;
@@ -1270,7 +1303,7 @@ static ssize_t omapfb_show_caps_num(struct device *dev,
1270static ssize_t omapfb_show_caps_text(struct device *dev, 1303static ssize_t omapfb_show_caps_text(struct device *dev,
1271 struct device_attribute *attr, char *buf) 1304 struct device_attribute *attr, char *buf)
1272{ 1305{
1273 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1306 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1274 int i; 1307 int i;
1275 struct omapfb_caps caps; 1308 struct omapfb_caps caps;
1276 int plane; 1309 int plane;
@@ -1317,7 +1350,7 @@ static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
1317static ssize_t omapfb_show_panel_name(struct device *dev, 1350static ssize_t omapfb_show_panel_name(struct device *dev,
1318 struct device_attribute *attr, char *buf) 1351 struct device_attribute *attr, char *buf)
1319{ 1352{
1320 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1353 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1321 1354
1322 return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name); 1355 return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
1323} 1356}
@@ -1326,7 +1359,7 @@ static ssize_t omapfb_show_bklight_level(struct device *dev,
1326 struct device_attribute *attr, 1359 struct device_attribute *attr,
1327 char *buf) 1360 char *buf)
1328{ 1361{
1329 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1362 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1330 int r; 1363 int r;
1331 1364
1332 if (fbdev->panel->get_bklight_level) { 1365 if (fbdev->panel->get_bklight_level) {
@@ -1341,7 +1374,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
1341 struct device_attribute *attr, 1374 struct device_attribute *attr,
1342 const char *buf, size_t size) 1375 const char *buf, size_t size)
1343{ 1376{
1344 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1377 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1345 int r; 1378 int r;
1346 1379
1347 if (fbdev->panel->set_bklight_level) { 1380 if (fbdev->panel->set_bklight_level) {
@@ -1360,7 +1393,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
1360static ssize_t omapfb_show_bklight_max(struct device *dev, 1393static ssize_t omapfb_show_bklight_max(struct device *dev,
1361 struct device_attribute *attr, char *buf) 1394 struct device_attribute *attr, char *buf)
1362{ 1395{
1363 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1396 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1364 int r; 1397 int r;
1365 1398
1366 if (fbdev->panel->get_bklight_level) { 1399 if (fbdev->panel->get_bklight_level) {
@@ -1393,7 +1426,7 @@ static struct attribute_group panel_attr_grp = {
1393static ssize_t omapfb_show_ctrl_name(struct device *dev, 1426static ssize_t omapfb_show_ctrl_name(struct device *dev,
1394 struct device_attribute *attr, char *buf) 1427 struct device_attribute *attr, char *buf)
1395{ 1428{
1396 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data; 1429 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1397 1430
1398 return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name); 1431 return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
1399} 1432}
@@ -1477,7 +1510,7 @@ static int fbinfo_init(struct omapfb_device *fbdev, struct fb_info *info)
1477 var->bits_per_pixel = fbdev->panel->bpp; 1510 var->bits_per_pixel = fbdev->panel->bpp;
1478 1511
1479 set_fb_var(info, var); 1512 set_fb_var(info, var);
1480 set_fb_fix(info); 1513 set_fb_fix(info, 1);
1481 1514
1482 r = fb_alloc_cmap(&info->cmap, 16, 0); 1515 r = fb_alloc_cmap(&info->cmap, 16, 0);
1483 if (r != 0) 1516 if (r != 0)
@@ -1695,8 +1728,8 @@ static int omapfb_do_probe(struct platform_device *pdev,
1695 1728
1696 pr_info("omapfb: configured for panel %s\n", fbdev->panel->name); 1729 pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
1697 1730
1698 def_vxres = def_vxres ? : fbdev->panel->x_res; 1731 def_vxres = def_vxres ? def_vxres : fbdev->panel->x_res;
1699 def_vyres = def_vyres ? : fbdev->panel->y_res; 1732 def_vyres = def_vyres ? def_vyres : fbdev->panel->y_res;
1700 1733
1701 init_state++; 1734 init_state++;
1702 1735
@@ -1818,8 +1851,8 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg)
1818{ 1851{
1819 struct omapfb_device *fbdev = platform_get_drvdata(pdev); 1852 struct omapfb_device *fbdev = platform_get_drvdata(pdev);
1820 1853
1821 omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); 1854 if (fbdev != NULL)
1822 1855 omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]);
1823 return 0; 1856 return 0;
1824} 1857}
1825 1858
@@ -1828,7 +1861,8 @@ static int omapfb_resume(struct platform_device *pdev)
1828{ 1861{
1829 struct omapfb_device *fbdev = platform_get_drvdata(pdev); 1862 struct omapfb_device *fbdev = platform_get_drvdata(pdev);
1830 1863
1831 omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); 1864 if (fbdev != NULL)
1865 omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]);
1832 return 0; 1866 return 0;
1833} 1867}
1834 1868
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 9332d6ca6456..ee01e84e19c1 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -57,6 +57,7 @@
57 57
58#define DISPC_BASE 0x48050400 58#define DISPC_BASE 0x48050400
59#define DISPC_CONTROL 0x0040 59#define DISPC_CONTROL 0x0040
60#define DISPC_IRQ_FRAMEMASK 0x0001
60 61
61static struct { 62static struct {
62 void __iomem *base; 63 void __iomem *base;
@@ -553,7 +554,9 @@ static int rfbi_init(struct omapfb_device *fbdev)
553 l = (0x01 << 2); 554 l = (0x01 << 2);
554 rfbi_write_reg(RFBI_CONTROL, l); 555 rfbi_write_reg(RFBI_CONTROL, l);
555 556
556 if ((r = omap_dispc_request_irq(rfbi_dma_callback, NULL)) < 0) { 557 r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback,
558 NULL);
559 if (r < 0) {
557 dev_err(fbdev->dev, "can't get DISPC irq\n"); 560 dev_err(fbdev->dev, "can't get DISPC irq\n");
558 rfbi_enable_clocks(0); 561 rfbi_enable_clocks(0);
559 return r; 562 return r;
@@ -570,7 +573,7 @@ static int rfbi_init(struct omapfb_device *fbdev)
570 573
571static void rfbi_cleanup(void) 574static void rfbi_cleanup(void)
572{ 575{
573 omap_dispc_free_irq(); 576 omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL);
574 rfbi_put_clocks(); 577 rfbi_put_clocks();
575 iounmap(rfbi.base); 578 iounmap(rfbi.base);
576} 579}
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 03b3670130a0..0a366d86f08e 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info)
141 offset = 0x10; 141 offset = 0x10;
142 142
143 info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; 143 info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
144 mutex_lock(&info->mm_lock);
144 info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; 145 info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
146 mutex_unlock(&info->mm_lock);
145 info->fix.visual = (pinfo->cmode == CMODE_8) ? 147 info->fix.visual = (pinfo->cmode == CMODE_8) ?
146 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; 148 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
147 info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) 149 info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
@@ -221,10 +223,14 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
221 223
222static inline int platinum_vram_reqd(int video_mode, int color_mode) 224static inline int platinum_vram_reqd(int video_mode, int color_mode)
223{ 225{
224 return vmode_attrs[video_mode-1].vres * 226 int baseval = vmode_attrs[video_mode-1].hres * (1<<color_mode);
225 (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 227
226 ((video_mode == VMODE_832_624_75) && 228 if ((video_mode == VMODE_832_624_75) && (color_mode > CMODE_8))
227 (color_mode > CMODE_8)) ? 0x10 : 0x20) + 0x1000; 229 baseval += 0x10;
230 else
231 baseval += 0x20;
232
233 return vmode_attrs[video_mode-1].vres * baseval + 0x1000;
228} 234}
229 235
230#define STORE_D2(a, d) { \ 236#define STORE_D2(a, d) { \
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index c0af638fe702..9c0144ee7ae5 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -32,7 +32,7 @@
32#include <linux/init.h> 32#include <linux/init.h>
33 33
34#include <asm/abs_addr.h> 34#include <asm/abs_addr.h>
35#include <asm/iommu.h> 35#include <asm/cell-regs.h>
36#include <asm/lv1call.h> 36#include <asm/lv1call.h>
37#include <asm/ps3av.h> 37#include <asm/ps3av.h>
38#include <asm/ps3fb.h> 38#include <asm/ps3fb.h>
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 0889d50c3288..1820c4a24434 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
815 ofb->video_mem_phys = virt_to_phys(ofb->video_mem); 815 ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
816 ofb->video_mem_size = size; 816 ofb->video_mem_size = size;
817 817
818 mutex_lock(&ofb->fb.mm_lock);
818 ofb->fb.fix.smem_start = ofb->video_mem_phys; 819 ofb->fb.fix.smem_start = ofb->video_mem_phys;
819 ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; 820 ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual;
821 mutex_unlock(&ofb->fb.mm_lock);
820 ofb->fb.screen_base = ofb->video_mem; 822 ofb->fb.screen_base = ofb->video_mem;
821 return 0; 823 return 0;
822} 824}
@@ -1636,24 +1638,26 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
1636 * Power management hooks. Note that we won't be called from IRQ context, 1638 * Power management hooks. Note that we won't be called from IRQ context,
1637 * unlike the blank functions above, so we may sleep. 1639 * unlike the blank functions above, so we may sleep.
1638 */ 1640 */
1639static int pxafb_suspend(struct platform_device *dev, pm_message_t state) 1641static int pxafb_suspend(struct device *dev)
1640{ 1642{
1641 struct pxafb_info *fbi = platform_get_drvdata(dev); 1643 struct pxafb_info *fbi = dev_get_drvdata(dev);
1642 1644
1643 set_ctrlr_state(fbi, C_DISABLE_PM); 1645 set_ctrlr_state(fbi, C_DISABLE_PM);
1644 return 0; 1646 return 0;
1645} 1647}
1646 1648
1647static int pxafb_resume(struct platform_device *dev) 1649static int pxafb_resume(struct device *dev)
1648{ 1650{
1649 struct pxafb_info *fbi = platform_get_drvdata(dev); 1651 struct pxafb_info *fbi = dev_get_drvdata(dev);
1650 1652
1651 set_ctrlr_state(fbi, C_ENABLE_PM); 1653 set_ctrlr_state(fbi, C_ENABLE_PM);
1652 return 0; 1654 return 0;
1653} 1655}
1654#else 1656
1655#define pxafb_suspend NULL 1657static struct dev_pm_ops pxafb_pm_ops = {
1656#define pxafb_resume NULL 1658 .suspend = pxafb_suspend,
1659 .resume = pxafb_resume,
1660};
1657#endif 1661#endif
1658 1662
1659static int __devinit pxafb_init_video_memory(struct pxafb_info *fbi) 1663static int __devinit pxafb_init_video_memory(struct pxafb_info *fbi)
@@ -2079,6 +2083,9 @@ static int __devinit pxafb_probe(struct platform_device *dev)
2079 goto failed; 2083 goto failed;
2080 } 2084 }
2081 2085
2086 if (cpu_is_pxa3xx() && inf->acceleration_enabled)
2087 fbi->fb.fix.accel = FB_ACCEL_PXA3XX;
2088
2082 fbi->backlight_power = inf->pxafb_backlight_power; 2089 fbi->backlight_power = inf->pxafb_backlight_power;
2083 fbi->lcd_power = inf->pxafb_lcd_power; 2090 fbi->lcd_power = inf->pxafb_lcd_power;
2084 2091
@@ -2089,14 +2096,14 @@ static int __devinit pxafb_probe(struct platform_device *dev)
2089 goto failed_fbi; 2096 goto failed_fbi;
2090 } 2097 }
2091 2098
2092 r = request_mem_region(r->start, r->end - r->start + 1, dev->name); 2099 r = request_mem_region(r->start, resource_size(r), dev->name);
2093 if (r == NULL) { 2100 if (r == NULL) {
2094 dev_err(&dev->dev, "failed to request I/O memory\n"); 2101 dev_err(&dev->dev, "failed to request I/O memory\n");
2095 ret = -EBUSY; 2102 ret = -EBUSY;
2096 goto failed_fbi; 2103 goto failed_fbi;
2097 } 2104 }
2098 2105
2099 fbi->mmio_base = ioremap(r->start, r->end - r->start + 1); 2106 fbi->mmio_base = ioremap(r->start, resource_size(r));
2100 if (fbi->mmio_base == NULL) { 2107 if (fbi->mmio_base == NULL) {
2101 dev_err(&dev->dev, "failed to map I/O memory\n"); 2108 dev_err(&dev->dev, "failed to map I/O memory\n");
2102 ret = -EBUSY; 2109 ret = -EBUSY;
@@ -2195,7 +2202,7 @@ failed_free_dma:
2195failed_free_io: 2202failed_free_io:
2196 iounmap(fbi->mmio_base); 2203 iounmap(fbi->mmio_base);
2197failed_free_res: 2204failed_free_res:
2198 release_mem_region(r->start, r->end - r->start + 1); 2205 release_mem_region(r->start, resource_size(r));
2199failed_fbi: 2206failed_fbi:
2200 clk_put(fbi->clk); 2207 clk_put(fbi->clk);
2201 platform_set_drvdata(dev, NULL); 2208 platform_set_drvdata(dev, NULL);
@@ -2235,7 +2242,7 @@ static int __devexit pxafb_remove(struct platform_device *dev)
2235 iounmap(fbi->mmio_base); 2242 iounmap(fbi->mmio_base);
2236 2243
2237 r = platform_get_resource(dev, IORESOURCE_MEM, 0); 2244 r = platform_get_resource(dev, IORESOURCE_MEM, 0);
2238 release_mem_region(r->start, r->end - r->start + 1); 2245 release_mem_region(r->start, resource_size(r));
2239 2246
2240 clk_put(fbi->clk); 2247 clk_put(fbi->clk);
2241 kfree(fbi); 2248 kfree(fbi);
@@ -2246,11 +2253,12 @@ static int __devexit pxafb_remove(struct platform_device *dev)
2246static struct platform_driver pxafb_driver = { 2253static struct platform_driver pxafb_driver = {
2247 .probe = pxafb_probe, 2254 .probe = pxafb_probe,
2248 .remove = __devexit_p(pxafb_remove), 2255 .remove = __devexit_p(pxafb_remove),
2249 .suspend = pxafb_suspend,
2250 .resume = pxafb_resume,
2251 .driver = { 2256 .driver = {
2252 .owner = THIS_MODULE, 2257 .owner = THIS_MODULE,
2253 .name = "pxa2xx-fb", 2258 .name = "pxa2xx-fb",
2259#ifdef CONFIG_PM
2260 .pm = &pxafb_pm_ops,
2261#endif
2254 }, 2262 },
2255}; 2263};
2256 2264
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 43680e545427..adf9632c6b1f 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -211,23 +211,21 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
211 211
212/** 212/**
213 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. 213 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
214 * @id: window id.
214 * @sfb: The hardware state. 215 * @sfb: The hardware state.
215 * @pixclock: The pixel clock wanted, in picoseconds. 216 * @pixclock: The pixel clock wanted, in picoseconds.
216 * 217 *
217 * Given the specified pixel clock, work out the necessary divider to get 218 * Given the specified pixel clock, work out the necessary divider to get
218 * close to the output frequency. 219 * close to the output frequency.
219 */ 220 */
220static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) 221static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk)
221{ 222{
223 struct s3c_fb_pd_win *win = sfb->pdata->win[id];
222 unsigned long clk = clk_get_rate(sfb->bus_clk); 224 unsigned long clk = clk_get_rate(sfb->bus_clk);
223 unsigned long long tmp;
224 unsigned int result; 225 unsigned int result;
225 226
226 tmp = (unsigned long long)clk; 227 pixclk *= win->win_mode.refresh;
227 tmp *= pixclk; 228 result = clk / pixclk;
228
229 do_div(tmp, 1000000000UL);
230 result = (unsigned int)tmp / 1000;
231 229
232 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", 230 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
233 pixclk, clk, result, clk / result); 231 pixclk, clk, result, clk / result);
@@ -267,6 +265,7 @@ static int s3c_fb_set_par(struct fb_info *info)
267 struct s3c_fb *sfb = win->parent; 265 struct s3c_fb *sfb = win->parent;
268 void __iomem *regs = sfb->regs; 266 void __iomem *regs = sfb->regs;
269 int win_no = win->index; 267 int win_no = win->index;
268 u32 osdc_data = 0;
270 u32 data; 269 u32 data;
271 u32 pagewidth; 270 u32 pagewidth;
272 int clkdiv; 271 int clkdiv;
@@ -302,7 +301,7 @@ static int s3c_fb_set_par(struct fb_info *info)
302 /* use window 0 as the basis for the lcd output timings */ 301 /* use window 0 as the basis for the lcd output timings */
303 302
304 if (win_no == 0) { 303 if (win_no == 0) {
305 clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); 304 clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock);
306 305
307 data = sfb->pdata->vidcon0; 306 data = sfb->pdata->vidcon0;
308 data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); 307 data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
@@ -359,8 +358,6 @@ static int s3c_fb_set_par(struct fb_info *info)
359 358
360 data = var->xres * var->yres; 359 data = var->xres * var->yres;
361 360
362 u32 osdc_data = 0;
363
364 osdc_data = VIDISD14C_ALPHA1_R(0xf) | 361 osdc_data = VIDISD14C_ALPHA1_R(0xf) |
365 VIDISD14C_ALPHA1_G(0xf) | 362 VIDISD14C_ALPHA1_G(0xf) |
366 VIDISD14C_ALPHA1_B(0xf); 363 VIDISD14C_ALPHA1_B(0xf);
@@ -967,7 +964,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
967 struct s3c_fb *sfb = platform_get_drvdata(pdev); 964 struct s3c_fb *sfb = platform_get_drvdata(pdev);
968 int win; 965 int win;
969 966
970 for (win = 0; win <= S3C_FB_MAX_WIN; win++) 967 for (win = 0; win < S3C_FB_MAX_WIN; win++)
971 if (sfb->windows[win]) 968 if (sfb->windows[win])
972 s3c_fb_release_win(sfb, sfb->windows[win]); 969 s3c_fb_release_win(sfb, sfb->windows[win]);
973 970
@@ -991,7 +988,7 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
991 struct s3c_fb_win *win; 988 struct s3c_fb_win *win;
992 int win_no; 989 int win_no;
993 990
994 for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) { 991 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
995 win = sfb->windows[win_no]; 992 win = sfb->windows[win_no];
996 if (!win) 993 if (!win)
997 continue; 994 continue;
@@ -1039,7 +1036,7 @@ static int s3c_fb_resume(struct platform_device *pdev)
1039 1036
1040static struct platform_driver s3c_fb_driver = { 1037static struct platform_driver s3c_fb_driver = {
1041 .probe = s3c_fb_probe, 1038 .probe = s3c_fb_probe,
1042 .remove = s3c_fb_remove, 1039 .remove = __devexit_p(s3c_fb_remove),
1043 .suspend = s3c_fb_suspend, 1040 .suspend = s3c_fb_suspend,
1044 .resume = s3c_fb_resume, 1041 .resume = s3c_fb_resume,
1045 .driver = { 1042 .driver = {
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 7da0027e2409..aac661225c78 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -369,7 +369,9 @@ static void s3c2410fb_activate_var(struct fb_info *info)
369 void __iomem *regs = fbi->io; 369 void __iomem *regs = fbi->io;
370 int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT; 370 int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;
371 struct fb_var_screeninfo *var = &info->var; 371 struct fb_var_screeninfo *var = &info->var;
372 int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock) / 2; 372 int clkdiv;
373
374 clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2);
373 375
374 dprintk("%s: var->xres = %d\n", __func__, var->xres); 376 dprintk("%s: var->xres = %d\n", __func__, var->xres);
375 dprintk("%s: var->yres = %d\n", __func__, var->yres); 377 dprintk("%s: var->yres = %d\n", __func__, var->yres);
@@ -1119,7 +1121,7 @@ int __init s3c2410fb_init(void)
1119 int ret = platform_driver_register(&s3c2410fb_driver); 1121 int ret = platform_driver_register(&s3c2410fb_driver);
1120 1122
1121 if (ret == 0) 1123 if (ret == 0)
1122 ret = platform_driver_register(&s3c2412fb_driver);; 1124 ret = platform_driver_register(&s3c2412fb_driver);
1123 1125
1124 return ret; 1126 return ret;
1125} 1127}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 10ddad8e17d6..cdaa873a6054 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -66,7 +66,7 @@
66 * - FrameBuffer memory is now allocated at run-time when the 66 * - FrameBuffer memory is now allocated at run-time when the
67 * driver is initialized. 67 * driver is initialized.
68 * 68 *
69 * 2000/04/10: Nicolas Pitre <nico@cam.org> 69 * 2000/04/10: Nicolas Pitre <nico@fluxnic.net>
70 * - Big cleanup for dynamic selection of machine type at run time. 70 * - Big cleanup for dynamic selection of machine type at run time.
71 * 71 *
72 * 2000/07/19: Jamey Hicks <jamey@crl.dec.com> 72 * 2000/07/19: Jamey Hicks <jamey@crl.dec.com>
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 37b135d5d12e..842d157e1025 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1565,7 +1565,7 @@ static int savagefb_blank(int blank, struct fb_info *info)
1565 vga_out8(0x3c5, sr8, par); 1565 vga_out8(0x3c5, sr8, par);
1566 vga_out8(0x3c4, 0x0d, par); 1566 vga_out8(0x3c4, 0x0d, par);
1567 srd = vga_in8(0x3c5, par); 1567 srd = vga_in8(0x3c5, par);
1568 srd &= 0x03; 1568 srd &= 0x50;
1569 1569
1570 switch (blank) { 1570 switch (blank) {
1571 case FB_BLANK_UNBLANK: 1571 case FB_BLANK_UNBLANK:
@@ -1606,22 +1606,6 @@ static int savagefb_blank(int blank, struct fb_info *info)
1606 return (blank == FB_BLANK_NORMAL) ? 1 : 0; 1606 return (blank == FB_BLANK_NORMAL) ? 1 : 0;
1607} 1607}
1608 1608
1609static void savagefb_save_state(struct fb_info *info)
1610{
1611 struct savagefb_par *par = info->par;
1612
1613 savage_get_default_par(par, &par->save);
1614}
1615
1616static void savagefb_restore_state(struct fb_info *info)
1617{
1618 struct savagefb_par *par = info->par;
1619
1620 savagefb_blank(FB_BLANK_POWERDOWN, info);
1621 savage_set_default_par(par, &par->save);
1622 savagefb_blank(FB_BLANK_UNBLANK, info);
1623}
1624
1625static int savagefb_open(struct fb_info *info, int user) 1609static int savagefb_open(struct fb_info *info, int user)
1626{ 1610{
1627 struct savagefb_par *par = info->par; 1611 struct savagefb_par *par = info->par;
@@ -1667,8 +1651,6 @@ static struct fb_ops savagefb_ops = {
1667 .fb_setcolreg = savagefb_setcolreg, 1651 .fb_setcolreg = savagefb_setcolreg,
1668 .fb_pan_display = savagefb_pan_display, 1652 .fb_pan_display = savagefb_pan_display,
1669 .fb_blank = savagefb_blank, 1653 .fb_blank = savagefb_blank,
1670 .fb_save_state = savagefb_save_state,
1671 .fb_restore_state = savagefb_restore_state,
1672#if defined(CONFIG_FB_SAVAGE_ACCEL) 1654#if defined(CONFIG_FB_SAVAGE_ACCEL)
1673 .fb_fillrect = savagefb_fillrect, 1655 .fb_fillrect = savagefb_fillrect,
1674 .fb_copyarea = savagefb_copyarea, 1656 .fb_copyarea = savagefb_copyarea,
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index 653bdfee3057..9f6d6e61f0cc 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno,
120 return 0; 120 return 0;
121} 121}
122 122
123static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
124 unsigned long stride)
125{
126 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
127 strcpy(fix->id, "sh7760-lcdc");
128
129 fix->smem_start = (unsigned long)info->screen_base;
130 fix->smem_len = info->screen_size;
131
132 fix->line_length = stride;
133}
134
135static int sh7760fb_get_color_info(struct device *dev, 123static int sh7760fb_get_color_info(struct device *dev,
136 u16 lddfr, int *bpp, int *gray) 124 u16 lddfr, int *bpp, int *gray)
137{ 125{
@@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info)
334 322
335 iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ 323 iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */
336 324
337 encode_fix(&info->fix, info, stride); 325 info->fix.line_length = stride;
326
338 sh7760fb_check_var(&info->var, info); 327 sh7760fb_check_var(&info->var, info);
339 328
340 sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ 329 sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
@@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info)
435 424
436 info->screen_base = fbmem; 425 info->screen_base = fbmem;
437 info->screen_size = vram; 426 info->screen_size = vram;
427 info->fix.smem_start = (unsigned long)info->screen_base;
428 info->fix.smem_len = info->screen_size;
438 429
439 return 0; 430 return 0;
440} 431}
@@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev)
520 info->var.transp.length = 0; 511 info->var.transp.length = 0;
521 info->var.transp.msb_right = 0; 512 info->var.transp.msb_right = 0;
522 513
514 strcpy(info->fix.id, "sh7760-lcdc");
515
523 /* set the DON2 bit now, before cmap allocation, as it will randomize 516 /* set the DON2 bit now, before cmap allocation, as it will randomize
524 * palette memory. 517 * palette memory.
525 */ 518 */
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index f10d2fbeda06..3ad5157f9899 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -14,41 +14,17 @@
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/fb.h> 15#include <linux/fb.h>
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/pm_runtime.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
19#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/vmalloc.h>
20#include <video/sh_mobile_lcdc.h> 22#include <video/sh_mobile_lcdc.h>
21#include <asm/atomic.h> 23#include <asm/atomic.h>
22 24
23#define PALETTE_NR 16 25#define PALETTE_NR 16
24 26#define SIDE_B_OFFSET 0x1000
25struct sh_mobile_lcdc_priv; 27#define MIRROR_OFFSET 0x2000
26struct sh_mobile_lcdc_chan {
27 struct sh_mobile_lcdc_priv *lcdc;
28 unsigned long *reg_offs;
29 unsigned long ldmt1r_value;
30 unsigned long enabled; /* ME and SE in LDCNT2R */
31 struct sh_mobile_lcdc_chan_cfg cfg;
32 u32 pseudo_palette[PALETTE_NR];
33 struct fb_info info;
34 dma_addr_t dma_handle;
35 struct fb_deferred_io defio;
36 unsigned long frame_end;
37 wait_queue_head_t frame_end_wait;
38};
39
40struct sh_mobile_lcdc_priv {
41 void __iomem *base;
42 int irq;
43#ifdef CONFIG_HAVE_CLK
44 atomic_t clk_usecnt;
45 struct clk *dot_clk;
46 struct clk *clk;
47#endif
48 unsigned long lddckr;
49 struct sh_mobile_lcdc_chan ch[2];
50 int started;
51};
52 28
53/* shared registers */ 29/* shared registers */
54#define _LDDCKR 0x410 30#define _LDDCKR 0x410
@@ -57,17 +33,30 @@ struct sh_mobile_lcdc_priv {
57#define _LDSR 0x46c 33#define _LDSR 0x46c
58#define _LDCNT1R 0x470 34#define _LDCNT1R 0x470
59#define _LDCNT2R 0x474 35#define _LDCNT2R 0x474
36#define _LDRCNTR 0x478
60#define _LDDDSR 0x47c 37#define _LDDDSR 0x47c
61#define _LDDWD0R 0x800 38#define _LDDWD0R 0x800
62#define _LDDRDR 0x840 39#define _LDDRDR 0x840
63#define _LDDWAR 0x900 40#define _LDDWAR 0x900
64#define _LDDRAR 0x904 41#define _LDDRAR 0x904
65 42
43/* shared registers and their order for context save/restore */
44static int lcdc_shared_regs[] = {
45 _LDDCKR,
46 _LDDCKSTPR,
47 _LDINTR,
48 _LDDDSR,
49 _LDCNT1R,
50 _LDCNT2R,
51};
52#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
53
66/* per-channel registers */ 54/* per-channel registers */
67enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, 55enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
68 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR }; 56 LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
57 NR_CH_REGS };
69 58
70static unsigned long lcdc_offs_mainlcd[] = { 59static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
71 [LDDCKPAT1R] = 0x400, 60 [LDDCKPAT1R] = 0x400,
72 [LDDCKPAT2R] = 0x404, 61 [LDDCKPAT2R] = 0x404,
73 [LDMT1R] = 0x418, 62 [LDMT1R] = 0x418,
@@ -85,7 +74,7 @@ static unsigned long lcdc_offs_mainlcd[] = {
85 [LDPMR] = 0x460, 74 [LDPMR] = 0x460,
86}; 75};
87 76
88static unsigned long lcdc_offs_sublcd[] = { 77static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
89 [LDDCKPAT1R] = 0x408, 78 [LDDCKPAT1R] = 0x408,
90 [LDDCKPAT2R] = 0x40c, 79 [LDDCKPAT2R] = 0x40c,
91 [LDMT1R] = 0x600, 80 [LDMT1R] = 0x600,
@@ -108,12 +97,80 @@ static unsigned long lcdc_offs_sublcd[] = {
108#define DISPLAY_BEU 0x00000008 97#define DISPLAY_BEU 0x00000008
109#define LCDC_ENABLE 0x00000001 98#define LCDC_ENABLE 0x00000001
110#define LDINTR_FE 0x00000400 99#define LDINTR_FE 0x00000400
100#define LDINTR_VSE 0x00000200
101#define LDINTR_VEE 0x00000100
111#define LDINTR_FS 0x00000004 102#define LDINTR_FS 0x00000004
103#define LDINTR_VSS 0x00000002
104#define LDINTR_VES 0x00000001
105#define LDRCNTR_SRS 0x00020000
106#define LDRCNTR_SRC 0x00010000
107#define LDRCNTR_MRS 0x00000002
108#define LDRCNTR_MRC 0x00000001
109
110struct sh_mobile_lcdc_priv;
111struct sh_mobile_lcdc_chan {
112 struct sh_mobile_lcdc_priv *lcdc;
113 unsigned long *reg_offs;
114 unsigned long ldmt1r_value;
115 unsigned long enabled; /* ME and SE in LDCNT2R */
116 struct sh_mobile_lcdc_chan_cfg cfg;
117 u32 pseudo_palette[PALETTE_NR];
118 unsigned long saved_ch_regs[NR_CH_REGS];
119 struct fb_info *info;
120 dma_addr_t dma_handle;
121 struct fb_deferred_io defio;
122 struct scatterlist *sglist;
123 unsigned long frame_end;
124 unsigned long pan_offset;
125 unsigned long new_pan_offset;
126 wait_queue_head_t frame_end_wait;
127};
128
129struct sh_mobile_lcdc_priv {
130 void __iomem *base;
131 int irq;
132 atomic_t hw_usecnt;
133 struct device *dev;
134 struct clk *dot_clk;
135 unsigned long lddckr;
136 struct sh_mobile_lcdc_chan ch[2];
137 unsigned long saved_shared_regs[NR_SHARED_REGS];
138 int started;
139};
140
141static bool banked(int reg_nr)
142{
143 switch (reg_nr) {
144 case LDMT1R:
145 case LDMT2R:
146 case LDMT3R:
147 case LDDFR:
148 case LDSM1R:
149 case LDSA1R:
150 case LDMLSR:
151 case LDHCNR:
152 case LDHSYNR:
153 case LDVLNR:
154 case LDVSYNR:
155 return true;
156 }
157 return false;
158}
112 159
113static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, 160static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
114 int reg_nr, unsigned long data) 161 int reg_nr, unsigned long data)
115{ 162{
116 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]); 163 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
164 if (banked(reg_nr))
165 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
166 SIDE_B_OFFSET);
167}
168
169static void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan,
170 int reg_nr, unsigned long data)
171{
172 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] +
173 MIRROR_OFFSET);
117} 174}
118 175
119static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, 176static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
@@ -154,6 +211,7 @@ static void lcdc_sys_write_index(void *handle, unsigned long data)
154 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); 211 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
155 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 212 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
156 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 213 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
214 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
157} 215}
158 216
159static void lcdc_sys_write_data(void *handle, unsigned long data) 217static void lcdc_sys_write_data(void *handle, unsigned long data)
@@ -163,6 +221,7 @@ static void lcdc_sys_write_data(void *handle, unsigned long data)
163 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); 221 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
164 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 222 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
165 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 223 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
224 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
166} 225}
167 226
168static unsigned long lcdc_sys_read_data(void *handle) 227static unsigned long lcdc_sys_read_data(void *handle)
@@ -173,8 +232,9 @@ static unsigned long lcdc_sys_read_data(void *handle)
173 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); 232 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
174 lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 233 lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
175 udelay(1); 234 udelay(1);
235 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
176 236
177 return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff; 237 return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff;
178} 238}
179 239
180struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { 240struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
@@ -183,11 +243,10 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
183 lcdc_sys_read_data, 243 lcdc_sys_read_data,
184}; 244};
185 245
186#ifdef CONFIG_HAVE_CLK
187static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 246static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
188{ 247{
189 if (atomic_inc_and_test(&priv->clk_usecnt)) { 248 if (atomic_inc_and_test(&priv->hw_usecnt)) {
190 clk_enable(priv->clk); 249 pm_runtime_get_sync(priv->dev);
191 if (priv->dot_clk) 250 if (priv->dot_clk)
192 clk_enable(priv->dot_clk); 251 clk_enable(priv->dot_clk);
193 } 252 }
@@ -195,27 +254,45 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
195 254
196static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) 255static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
197{ 256{
198 if (atomic_sub_return(1, &priv->clk_usecnt) == -1) { 257 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
199 if (priv->dot_clk) 258 if (priv->dot_clk)
200 clk_disable(priv->dot_clk); 259 clk_disable(priv->dot_clk);
201 clk_disable(priv->clk); 260 pm_runtime_put(priv->dev);
202 } 261 }
203} 262}
204#else 263
205static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {} 264static int sh_mobile_lcdc_sginit(struct fb_info *info,
206static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} 265 struct list_head *pagelist)
207#endif 266{
267 struct sh_mobile_lcdc_chan *ch = info->par;
268 unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT;
269 struct page *page;
270 int nr_pages = 0;
271
272 sg_init_table(ch->sglist, nr_pages_max);
273
274 list_for_each_entry(page, pagelist, lru)
275 sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
276
277 return nr_pages;
278}
208 279
209static void sh_mobile_lcdc_deferred_io(struct fb_info *info, 280static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
210 struct list_head *pagelist) 281 struct list_head *pagelist)
211{ 282{
212 struct sh_mobile_lcdc_chan *ch = info->par; 283 struct sh_mobile_lcdc_chan *ch = info->par;
284 unsigned int nr_pages;
213 285
214 /* enable clocks before accessing hardware */ 286 /* enable clocks before accessing hardware */
215 sh_mobile_lcdc_clk_on(ch->lcdc); 287 sh_mobile_lcdc_clk_on(ch->lcdc);
216 288
289 nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
290 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
291
217 /* trigger panel update */ 292 /* trigger panel update */
218 lcdc_write_chan(ch, LDSM2R, 1); 293 lcdc_write_chan(ch, LDSM2R, 1);
294
295 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
219} 296}
220 297
221static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) 298static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
@@ -231,30 +308,52 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
231 struct sh_mobile_lcdc_priv *priv = data; 308 struct sh_mobile_lcdc_priv *priv = data;
232 struct sh_mobile_lcdc_chan *ch; 309 struct sh_mobile_lcdc_chan *ch;
233 unsigned long tmp; 310 unsigned long tmp;
311 unsigned long ldintr;
234 int is_sub; 312 int is_sub;
235 int k; 313 int k;
236 314
237 /* acknowledge interrupt */ 315 /* acknowledge interrupt */
238 tmp = lcdc_read(priv, _LDINTR); 316 ldintr = tmp = lcdc_read(priv, _LDINTR);
239 tmp &= 0xffffff00; /* mask in high 24 bits */ 317 /*
240 tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */ 318 * disable further VSYNC End IRQs, preserve all other enabled IRQs,
319 * write 0 to bits 0-6 to ack all triggered IRQs.
320 */
321 tmp &= 0xffffff00 & ~LDINTR_VEE;
241 lcdc_write(priv, _LDINTR, tmp); 322 lcdc_write(priv, _LDINTR, tmp);
242 323
243 /* figure out if this interrupt is for main or sub lcd */ 324 /* figure out if this interrupt is for main or sub lcd */
244 is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; 325 is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0;
245 326
246 /* wake up channel and disable clocks*/ 327 /* wake up channel and disable clocks */
247 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 328 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
248 ch = &priv->ch[k]; 329 ch = &priv->ch[k];
249 330
250 if (!ch->enabled) 331 if (!ch->enabled)
251 continue; 332 continue;
252 333
253 if (is_sub == lcdc_chan_is_sublcd(ch)) { 334 /* Frame Start */
254 ch->frame_end = 1; 335 if (ldintr & LDINTR_FS) {
255 wake_up(&ch->frame_end_wait); 336 if (is_sub == lcdc_chan_is_sublcd(ch)) {
337 ch->frame_end = 1;
338 wake_up(&ch->frame_end_wait);
256 339
257 sh_mobile_lcdc_clk_off(priv); 340 sh_mobile_lcdc_clk_off(priv);
341 }
342 }
343
344 /* VSYNC End */
345 if (ldintr & LDINTR_VES) {
346 unsigned long ldrcntr = lcdc_read(priv, _LDRCNTR);
347 /* Set the source address for the next refresh */
348 lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle +
349 ch->new_pan_offset);
350 if (lcdc_chan_is_sublcd(ch))
351 lcdc_write(ch->lcdc, _LDRCNTR,
352 ldrcntr ^ LDRCNTR_SRS);
353 else
354 lcdc_write(ch->lcdc, _LDRCNTR,
355 ldrcntr ^ LDRCNTR_MRS);
356 ch->pan_offset = ch->new_pan_offset;
258 } 357 }
259 } 358 }
260 359
@@ -418,22 +517,22 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
418 /* set bpp format in PKF[4:0] */ 517 /* set bpp format in PKF[4:0] */
419 tmp = lcdc_read_chan(ch, LDDFR); 518 tmp = lcdc_read_chan(ch, LDDFR);
420 tmp &= ~(0x0001001f); 519 tmp &= ~(0x0001001f);
421 tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0; 520 tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
422 lcdc_write_chan(ch, LDDFR, tmp); 521 lcdc_write_chan(ch, LDDFR, tmp);
423 522
424 /* point out our frame buffer */ 523 /* point out our frame buffer */
425 lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start); 524 lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
426 525
427 /* set line size */ 526 /* set line size */
428 lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length); 527 lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
429 528
430 /* setup deferred io if SYS bus */ 529 /* setup deferred io if SYS bus */
431 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 530 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
432 if (ch->ldmt1r_value & (1 << 12) && tmp) { 531 if (ch->ldmt1r_value & (1 << 12) && tmp) {
433 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 532 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
434 ch->defio.delay = msecs_to_jiffies(tmp); 533 ch->defio.delay = msecs_to_jiffies(tmp);
435 ch->info.fbdefio = &ch->defio; 534 ch->info->fbdefio = &ch->defio;
436 fb_deferred_io_init(&ch->info); 535 fb_deferred_io_init(ch->info);
437 536
438 /* one-shot mode */ 537 /* one-shot mode */
439 lcdc_write_chan(ch, LDSM1R, 1); 538 lcdc_write_chan(ch, LDSM1R, 1);
@@ -457,6 +556,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
457 /* tell the board code to enable the panel */ 556 /* tell the board code to enable the panel */
458 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 557 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
459 ch = &priv->ch[k]; 558 ch = &priv->ch[k];
559 if (!ch->enabled)
560 continue;
561
460 board_cfg = &ch->cfg.board_cfg; 562 board_cfg = &ch->cfg.board_cfg;
461 if (board_cfg->display_on) 563 if (board_cfg->display_on)
462 board_cfg->display_on(board_cfg->board_data); 564 board_cfg->display_on(board_cfg->board_data);
@@ -474,24 +576,25 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
474 /* clean up deferred io and ask board code to disable panel */ 576 /* clean up deferred io and ask board code to disable panel */
475 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 577 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
476 ch = &priv->ch[k]; 578 ch = &priv->ch[k];
579 if (!ch->enabled)
580 continue;
477 581
478 /* deferred io mode: 582 /* deferred io mode:
479 * flush frame, and wait for frame end interrupt 583 * flush frame, and wait for frame end interrupt
480 * clean up deferred io and enable clock 584 * clean up deferred io and enable clock
481 */ 585 */
482 if (ch->info.fbdefio) { 586 if (ch->info->fbdefio) {
483 ch->frame_end = 0; 587 ch->frame_end = 0;
484 schedule_delayed_work(&ch->info.deferred_work, 0); 588 schedule_delayed_work(&ch->info->deferred_work, 0);
485 wait_event(ch->frame_end_wait, ch->frame_end); 589 wait_event(ch->frame_end_wait, ch->frame_end);
486 fb_deferred_io_cleanup(&ch->info); 590 fb_deferred_io_cleanup(ch->info);
487 ch->info.fbdefio = NULL; 591 ch->info->fbdefio = NULL;
488 sh_mobile_lcdc_clk_on(priv); 592 sh_mobile_lcdc_clk_on(priv);
489 } 593 }
490 594
491 board_cfg = &ch->cfg.board_cfg; 595 board_cfg = &ch->cfg.board_cfg;
492 if (board_cfg->display_off) 596 if (board_cfg->display_off)
493 board_cfg->display_off(board_cfg->board_data); 597 board_cfg->display_off(board_cfg->board_data);
494
495 } 598 }
496 599
497 /* stop the lcdc */ 600 /* stop the lcdc */
@@ -550,9 +653,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
550 int clock_source, 653 int clock_source,
551 struct sh_mobile_lcdc_priv *priv) 654 struct sh_mobile_lcdc_priv *priv)
552{ 655{
553#ifdef CONFIG_HAVE_CLK
554 char clk_name[8];
555#endif
556 char *str; 656 char *str;
557 int icksel; 657 int icksel;
558 658
@@ -566,25 +666,21 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
566 666
567 priv->lddckr = icksel << 16; 667 priv->lddckr = icksel << 16;
568 668
569#ifdef CONFIG_HAVE_CLK
570 atomic_set(&priv->clk_usecnt, -1);
571 snprintf(clk_name, sizeof(clk_name), "lcdc%d", pdev->id);
572 priv->clk = clk_get(&pdev->dev, clk_name);
573 if (IS_ERR(priv->clk)) {
574 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
575 return PTR_ERR(priv->clk);
576 }
577
578 if (str) { 669 if (str) {
579 priv->dot_clk = clk_get(&pdev->dev, str); 670 priv->dot_clk = clk_get(&pdev->dev, str);
580 if (IS_ERR(priv->dot_clk)) { 671 if (IS_ERR(priv->dot_clk)) {
581 dev_err(&pdev->dev, "cannot get dot clock %s\n", str); 672 dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
582 clk_put(priv->clk);
583 return PTR_ERR(priv->dot_clk); 673 return PTR_ERR(priv->dot_clk);
584 } 674 }
585 } 675 }
586#endif 676 atomic_set(&priv->hw_usecnt, -1);
587 677
678 /* Runtime PM support involves two step for this driver:
679 * 1) Enable Runtime PM
680 * 2) Force Runtime PM Resume since hardware is accessed from probe()
681 */
682 pm_runtime_enable(priv->dev);
683 pm_runtime_resume(priv->dev);
588 return 0; 684 return 0;
589} 685}
590 686
@@ -617,6 +713,9 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
617 .type = FB_TYPE_PACKED_PIXELS, 713 .type = FB_TYPE_PACKED_PIXELS,
618 .visual = FB_VISUAL_TRUECOLOR, 714 .visual = FB_VISUAL_TRUECOLOR,
619 .accel = FB_ACCEL_NONE, 715 .accel = FB_ACCEL_NONE,
716 .xpanstep = 0,
717 .ypanstep = 1,
718 .ywrapstep = 0,
620}; 719};
621 720
622static void sh_mobile_lcdc_fillrect(struct fb_info *info, 721static void sh_mobile_lcdc_fillrect(struct fb_info *info,
@@ -640,13 +739,38 @@ static void sh_mobile_lcdc_imageblit(struct fb_info *info,
640 sh_mobile_lcdc_deferred_io_touch(info); 739 sh_mobile_lcdc_deferred_io_touch(info);
641} 740}
642 741
742static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
743 struct fb_info *info)
744{
745 struct sh_mobile_lcdc_chan *ch = info->par;
746
747 if (info->var.xoffset == var->xoffset &&
748 info->var.yoffset == var->yoffset)
749 return 0; /* No change, do nothing */
750
751 ch->new_pan_offset = (var->yoffset * info->fix.line_length) +
752 (var->xoffset * (info->var.bits_per_pixel / 8));
753
754 if (ch->new_pan_offset != ch->pan_offset) {
755 unsigned long ldintr;
756 ldintr = lcdc_read(ch->lcdc, _LDINTR);
757 ldintr |= LDINTR_VEE;
758 lcdc_write(ch->lcdc, _LDINTR, ldintr);
759 sh_mobile_lcdc_deferred_io_touch(info);
760 }
761
762 return 0;
763}
764
643static struct fb_ops sh_mobile_lcdc_ops = { 765static struct fb_ops sh_mobile_lcdc_ops = {
766 .owner = THIS_MODULE,
644 .fb_setcolreg = sh_mobile_lcdc_setcolreg, 767 .fb_setcolreg = sh_mobile_lcdc_setcolreg,
645 .fb_read = fb_sys_read, 768 .fb_read = fb_sys_read,
646 .fb_write = fb_sys_write, 769 .fb_write = fb_sys_write,
647 .fb_fillrect = sh_mobile_lcdc_fillrect, 770 .fb_fillrect = sh_mobile_lcdc_fillrect,
648 .fb_copyarea = sh_mobile_lcdc_copyarea, 771 .fb_copyarea = sh_mobile_lcdc_copyarea,
649 .fb_imageblit = sh_mobile_lcdc_imageblit, 772 .fb_imageblit = sh_mobile_lcdc_imageblit,
773 .fb_pan_display = sh_mobile_fb_pan_display,
650}; 774};
651 775
652static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) 776static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
@@ -702,9 +826,59 @@ static int sh_mobile_lcdc_resume(struct device *dev)
702 return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); 826 return sh_mobile_lcdc_start(platform_get_drvdata(pdev));
703} 827}
704 828
829static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
830{
831 struct platform_device *pdev = to_platform_device(dev);
832 struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
833 struct sh_mobile_lcdc_chan *ch;
834 int k, n;
835
836 /* save per-channel registers */
837 for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
838 ch = &p->ch[k];
839 if (!ch->enabled)
840 continue;
841 for (n = 0; n < NR_CH_REGS; n++)
842 ch->saved_ch_regs[n] = lcdc_read_chan(ch, n);
843 }
844
845 /* save shared registers */
846 for (n = 0; n < NR_SHARED_REGS; n++)
847 p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]);
848
849 /* turn off LCDC hardware */
850 lcdc_write(p, _LDCNT1R, 0);
851 return 0;
852}
853
854static int sh_mobile_lcdc_runtime_resume(struct device *dev)
855{
856 struct platform_device *pdev = to_platform_device(dev);
857 struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev);
858 struct sh_mobile_lcdc_chan *ch;
859 int k, n;
860
861 /* restore per-channel registers */
862 for (k = 0; k < ARRAY_SIZE(p->ch); k++) {
863 ch = &p->ch[k];
864 if (!ch->enabled)
865 continue;
866 for (n = 0; n < NR_CH_REGS; n++)
867 lcdc_write_chan(ch, n, ch->saved_ch_regs[n]);
868 }
869
870 /* restore shared registers */
871 for (n = 0; n < NR_SHARED_REGS; n++)
872 lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]);
873
874 return 0;
875}
876
705static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { 877static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
706 .suspend = sh_mobile_lcdc_suspend, 878 .suspend = sh_mobile_lcdc_suspend,
707 .resume = sh_mobile_lcdc_resume, 879 .resume = sh_mobile_lcdc_resume,
880 .runtime_suspend = sh_mobile_lcdc_runtime_suspend,
881 .runtime_resume = sh_mobile_lcdc_runtime_resume,
708}; 882};
709 883
710static int sh_mobile_lcdc_remove(struct platform_device *pdev); 884static int sh_mobile_lcdc_remove(struct platform_device *pdev);
@@ -749,6 +923,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
749 } 923 }
750 924
751 priv->irq = i; 925 priv->irq = i;
926 priv->dev = &pdev->dev;
752 platform_set_drvdata(pdev, priv); 927 platform_set_drvdata(pdev, priv);
753 pdata = pdev->dev.platform_data; 928 pdata = pdev->dev.platform_data;
754 929
@@ -763,6 +938,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
763 goto err1; 938 goto err1;
764 } 939 }
765 init_waitqueue_head(&priv->ch[i].frame_end_wait); 940 init_waitqueue_head(&priv->ch[i].frame_end_wait);
941 priv->ch[j].pan_offset = 0;
942 priv->ch[j].new_pan_offset = 0;
766 943
767 switch (pdata->ch[i].chan) { 944 switch (pdata->ch[i].chan) {
768 case LCDC_CHAN_MAINLCD: 945 case LCDC_CHAN_MAINLCD:
@@ -793,12 +970,21 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
793 priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); 970 priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
794 971
795 for (i = 0; i < j; i++) { 972 for (i = 0; i < j; i++) {
796 info = &priv->ch[i].info;
797 cfg = &priv->ch[i].cfg; 973 cfg = &priv->ch[i].cfg;
798 974
975 priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
976 if (!priv->ch[i].info) {
977 dev_err(&pdev->dev, "unable to allocate fb_info\n");
978 error = -ENOMEM;
979 break;
980 }
981
982 info = priv->ch[i].info;
799 info->fbops = &sh_mobile_lcdc_ops; 983 info->fbops = &sh_mobile_lcdc_ops;
800 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; 984 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
801 info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; 985 info->var.yres = cfg->lcd_cfg.yres;
986 /* Default Y virtual resolution is 2x panel size */
987 info->var.yres_virtual = info->var.yres * 2;
802 info->var.width = cfg->lcd_size_cfg.width; 988 info->var.width = cfg->lcd_size_cfg.width;
803 info->var.height = cfg->lcd_size_cfg.height; 989 info->var.height = cfg->lcd_size_cfg.height;
804 info->var.activate = FB_ACTIVATE_NOW; 990 info->var.activate = FB_ACTIVATE_NOW;
@@ -808,7 +994,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
808 994
809 info->fix = sh_mobile_lcdc_fix; 995 info->fix = sh_mobile_lcdc_fix;
810 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); 996 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
811 info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres; 997 info->fix.smem_len = info->fix.line_length *
998 info->var.yres_virtual;
812 999
813 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, 1000 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
814 &priv->ch[i].dma_handle, GFP_KERNEL); 1001 &priv->ch[i].dma_handle, GFP_KERNEL);
@@ -846,21 +1033,31 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
846 } 1033 }
847 1034
848 for (i = 0; i < j; i++) { 1035 for (i = 0; i < j; i++) {
849 error = register_framebuffer(&priv->ch[i].info); 1036 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1037
1038 info = ch->info;
1039
1040 if (info->fbdefio) {
1041 priv->ch->sglist = vmalloc(sizeof(struct scatterlist) *
1042 info->fix.smem_len >> PAGE_SHIFT);
1043 if (!priv->ch->sglist) {
1044 dev_err(&pdev->dev, "cannot allocate sglist\n");
1045 goto err1;
1046 }
1047 }
1048
1049 error = register_framebuffer(info);
850 if (error < 0) 1050 if (error < 0)
851 goto err1; 1051 goto err1;
852 }
853 1052
854 for (i = 0; i < j; i++) {
855 info = &priv->ch[i].info;
856 dev_info(info->dev, 1053 dev_info(info->dev,
857 "registered %s/%s as %dx%d %dbpp.\n", 1054 "registered %s/%s as %dx%d %dbpp.\n",
858 pdev->name, 1055 pdev->name,
859 (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ? 1056 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
860 "mainlcd" : "sublcd", 1057 "mainlcd" : "sublcd",
861 (int) priv->ch[i].cfg.lcd_cfg.xres, 1058 (int) ch->cfg.lcd_cfg.xres,
862 (int) priv->ch[i].cfg.lcd_cfg.yres, 1059 (int) ch->cfg.lcd_cfg.yres,
863 priv->ch[i].cfg.bpp); 1060 ch->cfg.bpp);
864 1061
865 /* deferred io mode: disable clock to save power */ 1062 /* deferred io mode: disable clock to save power */
866 if (info->fbdefio) 1063 if (info->fbdefio)
@@ -881,27 +1078,30 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
881 int i; 1078 int i;
882 1079
883 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1080 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
884 if (priv->ch[i].info.dev) 1081 if (priv->ch[i].info->dev)
885 unregister_framebuffer(&priv->ch[i].info); 1082 unregister_framebuffer(priv->ch[i].info);
886 1083
887 sh_mobile_lcdc_stop(priv); 1084 sh_mobile_lcdc_stop(priv);
888 1085
889 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 1086 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
890 info = &priv->ch[i].info; 1087 info = priv->ch[i].info;
891 1088
892 if (!info->device) 1089 if (!info || !info->device)
893 continue; 1090 continue;
894 1091
1092 if (priv->ch[i].sglist)
1093 vfree(priv->ch[i].sglist);
1094
895 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1095 dma_free_coherent(&pdev->dev, info->fix.smem_len,
896 info->screen_base, priv->ch[i].dma_handle); 1096 info->screen_base, priv->ch[i].dma_handle);
897 fb_dealloc_cmap(&info->cmap); 1097 fb_dealloc_cmap(&info->cmap);
1098 framebuffer_release(info);
898 } 1099 }
899 1100
900#ifdef CONFIG_HAVE_CLK
901 if (priv->dot_clk) 1101 if (priv->dot_clk)
902 clk_put(priv->dot_clk); 1102 clk_put(priv->dot_clk);
903 clk_put(priv->clk); 1103
904#endif 1104 pm_runtime_disable(priv->dev);
905 1105
906 if (priv->base) 1106 if (priv->base)
907 iounmap(priv->base); 1107 iounmap(priv->base);
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 7072d19080d5..a4e05e4d7501 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -698,8 +698,8 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
698 rate, sisfb_vrate[i].refresh); 698 rate, sisfb_vrate[i].refresh);
699 ivideo->rate_idx = sisfb_vrate[i].idx; 699 ivideo->rate_idx = sisfb_vrate[i].idx;
700 ivideo->refresh_rate = sisfb_vrate[i].refresh; 700 ivideo->refresh_rate = sisfb_vrate[i].refresh;
701 } else if(((rate - sisfb_vrate[i-1].refresh) <= 2) 701 } else if((sisfb_vrate[i].idx != 1) &&
702 && (sisfb_vrate[i].idx != 1)) { 702 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n", 703 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
704 rate, sisfb_vrate[i-1].refresh); 704 rate, sisfb_vrate[i-1].refresh);
705 ivideo->rate_idx = sisfb_vrate[i-1].idx; 705 ivideo->rate_idx = sisfb_vrate[i-1].idx;
@@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1847 1847
1848 strcpy(fix->id, ivideo->myid); 1848 strcpy(fix->id, ivideo->myid);
1849 1849
1850 mutex_lock(&info->mm_lock);
1850 fix->smem_start = ivideo->video_base + ivideo->video_offset; 1851 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1851 fix->smem_len = ivideo->sisfb_mem; 1852 fix->smem_len = ivideo->sisfb_mem;
1853 mutex_unlock(&info->mm_lock);
1852 fix->type = FB_TYPE_PACKED_PIXELS; 1854 fix->type = FB_TYPE_PACKED_PIXELS;
1853 fix->type_aux = 0; 1855 fix->type_aux = 0;
1854 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 1856 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
@@ -6365,7 +6367,6 @@ error_3: vfree(ivideo->bios_abase);
6365 sis_fb_info->fix = ivideo->sisfb_fix; 6367 sis_fb_info->fix = ivideo->sisfb_fix;
6366 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset; 6368 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6367 sis_fb_info->fbops = &sisfb_ops; 6369 sis_fb_info->fbops = &sisfb_ops;
6368 sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
6369 sis_fb_info->pseudo_palette = ivideo->pseudo_palette; 6370 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6370 6371
6371 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0); 6372 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index 705c85360526..bef4aae388d0 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -342,7 +342,7 @@ struct SiS_Private
342 unsigned short SiS_RY4COE; 342 unsigned short SiS_RY4COE;
343 unsigned short SiS_LCDHDES; 343 unsigned short SiS_LCDHDES;
344 unsigned short SiS_LCDVDES; 344 unsigned short SiS_LCDVDES;
345 unsigned short SiS_DDC_Port; 345 SISIOADDRESS SiS_DDC_Port;
346 unsigned short SiS_DDC_Index; 346 unsigned short SiS_DDC_Index;
347 unsigned short SiS_DDC_Data; 347 unsigned short SiS_DDC_Data;
348 unsigned short SiS_DDC_NData; 348 unsigned short SiS_DDC_NData;
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index eb5d73a06702..924d79462780 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
145#define SM501_MEMF_ACCEL (8) 145#define SM501_MEMF_ACCEL (8)
146 146
147static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, 147static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
148 unsigned int why, size_t size) 148 unsigned int why, size_t size, u32 smem_len)
149{ 149{
150 struct sm501fb_par *par; 150 struct sm501fb_par *par;
151 struct fb_info *fbi; 151 struct fb_info *fbi;
@@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
172 if (ptr > 0) 172 if (ptr > 0)
173 ptr &= ~(PAGE_SIZE - 1); 173 ptr &= ~(PAGE_SIZE - 1);
174 174
175 if (fbi && ptr < fbi->fix.smem_len) 175 if (fbi && ptr < smem_len)
176 return -ENOMEM; 176 return -ENOMEM;
177 177
178 break; 178 break;
@@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
197 197
198 case SM501_MEMF_ACCEL: 198 case SM501_MEMF_ACCEL:
199 fbi = inf->fb[HEAD_CRT]; 199 fbi = inf->fb[HEAD_CRT];
200 ptr = fbi ? fbi->fix.smem_len : 0; 200 ptr = fbi ? smem_len : 0;
201 201
202 fbi = inf->fb[HEAD_PANEL]; 202 fbi = inf->fb[HEAD_PANEL];
203 if (fbi) { 203 if (fbi) {
@@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info,
413 unsigned int mem_type; 413 unsigned int mem_type;
414 unsigned int clock_type; 414 unsigned int clock_type;
415 unsigned int head_addr; 415 unsigned int head_addr;
416 unsigned int smem_len;
416 417
417 dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", 418 dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
418 __func__, var->xres, var->yres, var->bits_per_pixel, 419 __func__, var->xres, var->yres, var->bits_per_pixel,
@@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info,
453 454
454 /* allocate fb memory within 501 */ 455 /* allocate fb memory within 501 */
455 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; 456 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
456 info->fix.smem_len = info->fix.line_length * var->yres_virtual; 457 smem_len = info->fix.line_length * var->yres_virtual;
457 458
458 dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, 459 dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
459 info->fix.line_length); 460 info->fix.line_length);
460 461
461 if (sm501_alloc_mem(fbi, &par->screen, mem_type, 462 if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) {
462 info->fix.smem_len)) {
463 dev_err(fbi->dev, "no memory available\n"); 463 dev_err(fbi->dev, "no memory available\n");
464 return -ENOMEM; 464 return -ENOMEM;
465 } 465 }
466 466
467 mutex_lock(&info->mm_lock);
467 info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; 468 info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
469 info->fix.smem_len = smem_len;
470 mutex_unlock(&info->mm_lock);
468 471
469 info->screen_base = fbi->fbmem + par->screen.sm_addr; 472 info->screen_base = fbi->fbmem + par->screen.sm_addr;
470 info->screen_size = info->fix.smem_len; 473 info->screen_size = info->fix.smem_len;
@@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info)
637 if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { 640 if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
638 /* the head is displaying panel data... */ 641 /* the head is displaying panel data... */
639 642
640 sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); 643 sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0,
644 info->fix.smem_len);
641 goto out_update; 645 goto out_update;
642 } 646 }
643 647
@@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
1289 1293
1290 par->cursor_regs = info->regs + reg_base; 1294 par->cursor_regs = info->regs + reg_base;
1291 1295
1292 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); 1296 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024,
1297 fbi->fix.smem_len);
1293 if (ret < 0) 1298 if (ret < 0)
1294 return ret; 1299 return ret;
1295 1300
@@ -1535,9 +1540,6 @@ static int sm501fb_init_fb(struct fb_info *fb,
1535 if (ret) 1540 if (ret)
1536 dev_err(info->dev, "check_var() failed on initial setup?\n"); 1541 dev_err(info->dev, "check_var() failed on initial setup?\n");
1537 1542
1538 /* ensure we've activated our new configuration */
1539 (fb->fbops->fb_set_par)(fb);
1540
1541 return 0; 1543 return 0;
1542} 1544}
1543 1545
@@ -1619,6 +1621,8 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info,
1619 if (!fbi) 1621 if (!fbi)
1620 return 0; 1622 return 0;
1621 1623
1624 mutex_init(&info->fb[head]->mm_lock);
1625
1622 ret = sm501fb_init_fb(info->fb[head], head, drvname); 1626 ret = sm501fb_init_fb(info->fb[head], head, drvname);
1623 if (ret) { 1627 if (ret) {
1624 dev_err(info->dev, "cannot initialise fb %s\n", drvname); 1628 dev_err(info->dev, "cannot initialise fb %s\n", drvname);
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index eec9dcb7f599..6120f0c526fe 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1115,10 +1115,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
1115 if the device name contains the string "DX" and tell the 1115 if the device name contains the string "DX" and tell the
1116 user how to reconfigure the card. */ 1116 user how to reconfigure the card. */
1117 if (strstr(sti->outptr.dev_name, "DX")) { 1117 if (strstr(sti->outptr.dev_name, "DX")) {
1118 printk(KERN_WARNING "WARNING: stifb framebuffer driver does not " 1118 printk(KERN_WARNING
1119 "support '%s' in double-buffer mode.\n" 1119"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
1120 KERN_WARNING "WARNING: Please disable the double-buffer mode " 1120"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
1121 "in IPL menu (the PARISC-BIOS).\n",
1122 sti->outptr.dev_name); 1121 sti->outptr.dev_name);
1123 goto out_err0; 1122 goto out_err0;
1124 } 1123 }
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index a1eb0862255b..6913fe168c25 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -974,7 +974,7 @@ static int tmiofb_resume(struct platform_device *dev)
974{ 974{
975 struct fb_info *info = platform_get_drvdata(dev); 975 struct fb_info *info = platform_get_drvdata(dev);
976 struct mfd_cell *cell = dev->dev.platform_data; 976 struct mfd_cell *cell = dev->dev.platform_data;
977 int retval; 977 int retval = 0;
978 978
979 acquire_console_sem(); 979 acquire_console_sem();
980 980
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index ca5b4643a401..54fbb2995a5f 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -67,12 +67,14 @@ static DEFINE_MUTEX(uvfb_lock);
67 * find the kernel part of the task struct, copy the registers and 67 * find the kernel part of the task struct, copy the registers and
68 * the buffer contents and then complete the task. 68 * the buffer contents and then complete the task.
69 */ 69 */
70static void uvesafb_cn_callback(void *data) 70static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
71{ 71{
72 struct cn_msg *msg = data;
73 struct uvesafb_task *utask; 72 struct uvesafb_task *utask;
74 struct uvesafb_ktask *task; 73 struct uvesafb_ktask *task;
75 74
75 if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
76 return;
77
76 if (msg->seq >= UVESAFB_TASKS_MAX) 78 if (msg->seq >= UVESAFB_TASKS_MAX)
77 return; 79 return;
78 80
@@ -1409,23 +1411,6 @@ static int uvesafb_check_var(struct fb_var_screeninfo *var,
1409 return 0; 1411 return 0;
1410} 1412}
1411 1413
1412static void uvesafb_save_state(struct fb_info *info)
1413{
1414 struct uvesafb_par *par = info->par;
1415
1416 if (par->vbe_state_saved)
1417 kfree(par->vbe_state_saved);
1418
1419 par->vbe_state_saved = uvesafb_vbe_state_save(par);
1420}
1421
1422static void uvesafb_restore_state(struct fb_info *info)
1423{
1424 struct uvesafb_par *par = info->par;
1425
1426 uvesafb_vbe_state_restore(par, par->vbe_state_saved);
1427}
1428
1429static struct fb_ops uvesafb_ops = { 1414static struct fb_ops uvesafb_ops = {
1430 .owner = THIS_MODULE, 1415 .owner = THIS_MODULE,
1431 .fb_open = uvesafb_open, 1416 .fb_open = uvesafb_open,
@@ -1439,8 +1424,6 @@ static struct fb_ops uvesafb_ops = {
1439 .fb_imageblit = cfb_imageblit, 1424 .fb_imageblit = cfb_imageblit,
1440 .fb_check_var = uvesafb_check_var, 1425 .fb_check_var = uvesafb_check_var,
1441 .fb_set_par = uvesafb_set_par, 1426 .fb_set_par = uvesafb_set_par,
1442 .fb_save_state = uvesafb_save_state,
1443 .fb_restore_state = uvesafb_restore_state,
1444}; 1427};
1445 1428
1446static void __devinit uvesafb_init_info(struct fb_info *info, 1429static void __devinit uvesafb_init_info(struct fb_info *info,
@@ -1457,15 +1440,6 @@ static void __devinit uvesafb_init_info(struct fb_info *info,
1457 info->fix.ypanstep = par->ypan ? 1 : 0; 1440 info->fix.ypanstep = par->ypan ? 1 : 0;
1458 info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0; 1441 info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0;
1459 1442
1460 /*
1461 * If we were unable to get the state buffer size, disable
1462 * functions for saving and restoring the hardware state.
1463 */
1464 if (par->vbe_state_size == 0) {
1465 info->fbops->fb_save_state = NULL;
1466 info->fbops->fb_restore_state = NULL;
1467 }
1468
1469 /* Disable blanking if the user requested so. */ 1443 /* Disable blanking if the user requested so. */
1470 if (!blank) 1444 if (!blank)
1471 info->fbops->fb_blank = NULL; 1445 info->fbops->fb_blank = NULL;
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
index 45c54bfe99bb..9d4f3a49ba4a 100644
--- a/drivers/video/via/accel.c
+++ b/drivers/video/via/accel.c
@@ -20,229 +20,430 @@
20 */ 20 */
21#include "global.h" 21#include "global.h"
22 22
23void viafb_init_accel(void) 23static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
24 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
25 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
26 u32 fg_color, u32 bg_color, u8 fill_rop)
24{ 27{
25 viaparinfo->fbmem_free -= CURSOR_SIZE; 28 u32 ge_cmd = 0, tmp, i;
26 viaparinfo->cursor_start = viaparinfo->fbmem_free;
27 viaparinfo->fbmem_used += CURSOR_SIZE;
28 29
29 /* Reverse 8*1024 memory space for cursor image */ 30 if (!op || op > 3) {
30 viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE); 31 printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
31 viaparinfo->VQ_start = viaparinfo->fbmem_free; 32 return -EINVAL;
32 viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1; 33 }
33 viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); }
34
35void viafb_init_2d_engine(void)
36{
37 u32 dwVQStartAddr, dwVQEndAddr;
38 u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH;
39
40 /* init 2D engine regs to reset 2D engine */
41 writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE);
42 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
43 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS);
44 writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION);
45 writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR);
46 writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR);
47 writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR);
48 writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL);
49 writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR);
50 writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET);
51 writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL);
52 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
53 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
54 writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH);
55 writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1);
56
57 /* Init AGP and VQ regs */
58 switch (viaparinfo->chip_info->gfx_chip_name) {
59 case UNICHROME_K8M890:
60 case UNICHROME_P4M900:
61 writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET);
62 writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
63 writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
64 break;
65 34
66 default: 35 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
67 writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET); 36 if (src_x < dst_x) {
68 writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 37 ge_cmd |= 0x00008000;
69 writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE); 38 src_x += width - 1;
70 writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 39 dst_x += width - 1;
71 writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 40 }
72 writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 41 if (src_y < dst_y) {
73 writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 42 ge_cmd |= 0x00004000;
74 writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 43 src_y += height - 1;
75 writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE); 44 dst_y += height - 1;
76 45 }
77 writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET);
78 writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
79 break;
80 } 46 }
81 if (viaparinfo->VQ_start != 0) { 47
82 /* Enable VQ */ 48 if (op == VIA_BITBLT_FILL) {
83 dwVQStartAddr = viaparinfo->VQ_start; 49 switch (fill_rop) {
84 dwVQEndAddr = viaparinfo->VQ_end; 50 case 0x00: /* blackness */
85 51 case 0x5A: /* pattern inversion */
86 dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF); 52 case 0xF0: /* pattern copy */
87 dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF); 53 case 0xFF: /* whiteness */
88 dwVQStartEndH = 0x52000000 |
89 ((dwVQStartAddr & 0xFF000000) >> 24) |
90 ((dwVQEndAddr & 0xFF000000) >> 16);
91 dwVQLen = 0x53000000 | (VQ_SIZE >> 3);
92 switch (viaparinfo->chip_info->gfx_chip_name) {
93 case UNICHROME_K8M890:
94 case UNICHROME_P4M900:
95 dwVQStartL |= 0x20000000;
96 dwVQEndL |= 0x20000000;
97 dwVQStartEndH |= 0x20000000;
98 dwVQLen |= 0x20000000;
99 break; 54 break;
100 default: 55 default:
101 break; 56 printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
57 "%u\n", fill_rop);
58 return -EINVAL;
102 } 59 }
60 }
103 61
104 switch (viaparinfo->chip_info->gfx_chip_name) { 62 switch (dst_bpp) {
105 case UNICHROME_K8M890: 63 case 8:
106 case UNICHROME_P4M900: 64 tmp = 0x00000000;
107 writel(0x00100000, 65 break;
108 viaparinfo->io_virt + VIA_REG_CR_TRANSET); 66 case 16:
109 writel(dwVQStartEndH, 67 tmp = 0x00000100;
110 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 68 break;
111 writel(dwVQStartL, 69 case 32:
112 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 70 tmp = 0x00000300;
113 writel(dwVQEndL, 71 break;
114 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 72 default:
115 writel(dwVQLen, 73 printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n",
116 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 74 dst_bpp);
117 writel(0x74301001, 75 return -EINVAL;
118 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 76 }
119 writel(0x00000000, 77 writel(tmp, engine + 0x04);
120 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 78
121 break; 79 if (op != VIA_BITBLT_FILL) {
122 default: 80 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
123 writel(0x00FE0000, 81 || src_y & 0xFFFFF000) {
124 viaparinfo->io_virt + VIA_REG_TRANSET); 82 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
125 writel(0x080003FE, 83 "x/y %d %d\n", src_x, src_y);
126 viaparinfo->io_virt + VIA_REG_TRANSPACE); 84 return -EINVAL;
127 writel(0x0A00027C,
128 viaparinfo->io_virt + VIA_REG_TRANSPACE);
129 writel(0x0B000260,
130 viaparinfo->io_virt + VIA_REG_TRANSPACE);
131 writel(0x0C000274,
132 viaparinfo->io_virt + VIA_REG_TRANSPACE);
133 writel(0x0D000264,
134 viaparinfo->io_virt + VIA_REG_TRANSPACE);
135 writel(0x0E000000,
136 viaparinfo->io_virt + VIA_REG_TRANSPACE);
137 writel(0x0F000020,
138 viaparinfo->io_virt + VIA_REG_TRANSPACE);
139 writel(0x1000027E,
140 viaparinfo->io_virt + VIA_REG_TRANSPACE);
141 writel(0x110002FE,
142 viaparinfo->io_virt + VIA_REG_TRANSPACE);
143 writel(0x200F0060,
144 viaparinfo->io_virt + VIA_REG_TRANSPACE);
145
146 writel(0x00000006,
147 viaparinfo->io_virt + VIA_REG_TRANSPACE);
148 writel(0x40008C0F,
149 viaparinfo->io_virt + VIA_REG_TRANSPACE);
150 writel(0x44000000,
151 viaparinfo->io_virt + VIA_REG_TRANSPACE);
152 writel(0x45080C04,
153 viaparinfo->io_virt + VIA_REG_TRANSPACE);
154 writel(0x46800408,
155 viaparinfo->io_virt + VIA_REG_TRANSPACE);
156
157 writel(dwVQStartEndH,
158 viaparinfo->io_virt + VIA_REG_TRANSPACE);
159 writel(dwVQStartL,
160 viaparinfo->io_virt + VIA_REG_TRANSPACE);
161 writel(dwVQEndL,
162 viaparinfo->io_virt + VIA_REG_TRANSPACE);
163 writel(dwVQLen,
164 viaparinfo->io_virt + VIA_REG_TRANSPACE);
165 break;
166 } 85 }
167 } else { 86 tmp = src_x | (src_y << 16);
168 /* Disable VQ */ 87 writel(tmp, engine + 0x08);
169 switch (viaparinfo->chip_info->gfx_chip_name) { 88 }
170 case UNICHROME_K8M890: 89
171 case UNICHROME_P4M900: 90 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
172 writel(0x00100000, 91 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
173 viaparinfo->io_virt + VIA_REG_CR_TRANSET); 92 "%d %d\n", dst_x, dst_y);
174 writel(0x74301000, 93 return -EINVAL;
175 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE); 94 }
176 break; 95 tmp = dst_x | (dst_y << 16);
177 default: 96 writel(tmp, engine + 0x0C);
178 writel(0x00FE0000, 97
179 viaparinfo->io_virt + VIA_REG_TRANSET); 98 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
180 writel(0x00000004, 99 printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
181 viaparinfo->io_virt + VIA_REG_TRANSPACE); 100 "%d %d\n", width, height);
182 writel(0x40008C0F, 101 return -EINVAL;
183 viaparinfo->io_virt + VIA_REG_TRANSPACE); 102 }
184 writel(0x44000000, 103 tmp = (width - 1) | ((height - 1) << 16);
185 viaparinfo->io_virt + VIA_REG_TRANSPACE); 104 writel(tmp, engine + 0x10);
186 writel(0x45080C04, 105
187 viaparinfo->io_virt + VIA_REG_TRANSPACE); 106 if (op != VIA_BITBLT_COLOR)
188 writel(0x46800408, 107 writel(fg_color, engine + 0x18);
189 viaparinfo->io_virt + VIA_REG_TRANSPACE); 108
190 break; 109 if (op == VIA_BITBLT_MONO)
110 writel(bg_color, engine + 0x1C);
111
112 if (op != VIA_BITBLT_FILL) {
113 tmp = src_mem ? 0 : src_addr;
114 if (dst_addr & 0xE0000007) {
115 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
116 "address %X\n", tmp);
117 return -EINVAL;
191 } 118 }
119 tmp >>= 3;
120 writel(tmp, engine + 0x30);
121 }
122
123 if (dst_addr & 0xE0000007) {
124 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
125 "address %X\n", dst_addr);
126 return -EINVAL;
192 } 127 }
128 tmp = dst_addr >> 3;
129 writel(tmp, engine + 0x34);
193 130
194 viafb_set_2d_color_depth(viaparinfo->bpp); 131 if (op == VIA_BITBLT_FILL)
132 tmp = 0;
133 else
134 tmp = src_pitch;
135 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
136 printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
137 tmp, dst_pitch);
138 return -EINVAL;
139 }
140 tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
141 writel(tmp, engine + 0x38);
142
143 if (op == VIA_BITBLT_FILL)
144 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
145 else {
146 ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
147 if (src_mem)
148 ge_cmd |= 0x00000040;
149 if (op == VIA_BITBLT_MONO)
150 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
151 else
152 ge_cmd |= 0x00000001;
153 }
154 writel(ge_cmd, engine);
195 155
196 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE); 156 if (op == VIA_BITBLT_FILL || !src_mem)
197 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE); 157 return 0;
198 158
199 writel(VIA_PITCH_ENABLE | 159 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
200 (((viaparinfo->hres * 160 3) >> 2;
201 viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres * 161
202 viaparinfo-> 162 for (i = 0; i < tmp; i++)
203 bpp >> 3) >> 3) << 16)), 163 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
204 viaparinfo->io_virt + VIA_REG_PITCH); 164
165 return 0;
205} 166}
206 167
207void viafb_set_2d_color_depth(int bpp) 168static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
169 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
170 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
171 u32 fg_color, u32 bg_color, u8 fill_rop)
208{ 172{
209 u32 dwGEMode; 173 u32 ge_cmd = 0, tmp, i;
174
175 if (!op || op > 3) {
176 printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
177 return -EINVAL;
178 }
210 179
211 dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF; 180 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
181 if (src_x < dst_x) {
182 ge_cmd |= 0x00008000;
183 src_x += width - 1;
184 dst_x += width - 1;
185 }
186 if (src_y < dst_y) {
187 ge_cmd |= 0x00004000;
188 src_y += height - 1;
189 dst_y += height - 1;
190 }
191 }
212 192
213 switch (bpp) { 193 if (op == VIA_BITBLT_FILL) {
194 switch (fill_rop) {
195 case 0x00: /* blackness */
196 case 0x5A: /* pattern inversion */
197 case 0xF0: /* pattern copy */
198 case 0xFF: /* whiteness */
199 break;
200 default:
201 printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
202 "%u\n", fill_rop);
203 return -EINVAL;
204 }
205 }
206
207 switch (dst_bpp) {
208 case 8:
209 tmp = 0x00000000;
210 break;
214 case 16: 211 case 16:
215 dwGEMode |= VIA_GEM_16bpp; 212 tmp = 0x00000100;
216 break; 213 break;
217 case 32: 214 case 32:
218 dwGEMode |= VIA_GEM_32bpp; 215 tmp = 0x00000300;
219 break; 216 break;
220 default: 217 default:
221 dwGEMode |= VIA_GEM_8bpp; 218 printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n",
222 break; 219 dst_bpp);
220 return -EINVAL;
221 }
222 writel(tmp, engine + 0x04);
223
224 if (op == VIA_BITBLT_FILL)
225 tmp = 0;
226 else
227 tmp = src_pitch;
228 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
229 printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
230 tmp, dst_pitch);
231 return -EINVAL;
232 }
233 tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
234 writel(tmp, engine + 0x08);
235
236 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
237 printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
238 "%d %d\n", width, height);
239 return -EINVAL;
240 }
241 tmp = (width - 1) | ((height - 1) << 16);
242 writel(tmp, engine + 0x0C);
243
244 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
245 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
246 "%d %d\n", dst_x, dst_y);
247 return -EINVAL;
248 }
249 tmp = dst_x | (dst_y << 16);
250 writel(tmp, engine + 0x10);
251
252 if (dst_addr & 0xE0000007) {
253 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
254 "address %X\n", dst_addr);
255 return -EINVAL;
256 }
257 tmp = dst_addr >> 3;
258 writel(tmp, engine + 0x14);
259
260 if (op != VIA_BITBLT_FILL) {
261 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
262 || src_y & 0xFFFFF000) {
263 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
264 "x/y %d %d\n", src_x, src_y);
265 return -EINVAL;
266 }
267 tmp = src_x | (src_y << 16);
268 writel(tmp, engine + 0x18);
269
270 tmp = src_mem ? 0 : src_addr;
271 if (dst_addr & 0xE0000007) {
272 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
273 "address %X\n", tmp);
274 return -EINVAL;
275 }
276 tmp >>= 3;
277 writel(tmp, engine + 0x1C);
223 } 278 }
224 279
225 /* Set BPP and Pitch */ 280 if (op != VIA_BITBLT_COLOR)
226 writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE); 281 writel(fg_color, engine + 0x4C);
282
283 if (op == VIA_BITBLT_MONO)
284 writel(bg_color, engine + 0x50);
285
286 if (op == VIA_BITBLT_FILL)
287 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
288 else {
289 ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
290 if (src_mem)
291 ge_cmd |= 0x00000040;
292 if (op == VIA_BITBLT_MONO)
293 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
294 else
295 ge_cmd |= 0x00000001;
296 }
297 writel(ge_cmd, engine);
298
299 if (op == VIA_BITBLT_FILL || !src_mem)
300 return 0;
301
302 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
303 3) >> 2;
304
305 for (i = 0; i < tmp; i++)
306 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
307
308 return 0;
227} 309}
228 310
229void viafb_hw_cursor_init(void) 311int viafb_init_engine(struct fb_info *info)
230{ 312{
313 struct viafb_par *viapar = info->par;
314 void __iomem *engine;
315 u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
316 vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
317
318 engine = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
319 viapar->shared->engine_mmio = engine;
320 if (!engine) {
321 printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
322 "hardware acceleration disabled\n");
323 return -ENOMEM;
324 }
325
326 switch (chip_name) {
327 case UNICHROME_CLE266:
328 case UNICHROME_K400:
329 case UNICHROME_K800:
330 case UNICHROME_PM800:
331 case UNICHROME_CN700:
332 case UNICHROME_CX700:
333 case UNICHROME_CN750:
334 case UNICHROME_K8M890:
335 case UNICHROME_P4M890:
336 case UNICHROME_P4M900:
337 viapar->shared->hw_bitblt = hw_bitblt_1;
338 break;
339 case UNICHROME_VX800:
340 case UNICHROME_VX855:
341 viapar->shared->hw_bitblt = hw_bitblt_2;
342 break;
343 default:
344 viapar->shared->hw_bitblt = NULL;
345 }
346
347 viapar->fbmem_free -= CURSOR_SIZE;
348 viapar->shared->cursor_vram_addr = viapar->fbmem_free;
349 viapar->fbmem_used += CURSOR_SIZE;
350
351 viapar->fbmem_free -= VQ_SIZE;
352 viapar->shared->vq_vram_addr = viapar->fbmem_free;
353 viapar->fbmem_used += VQ_SIZE;
354
355 /* Init AGP and VQ regs */
356 switch (chip_name) {
357 case UNICHROME_K8M890:
358 case UNICHROME_P4M900:
359 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
360 writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
361 writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
362 break;
363
364 default:
365 writel(0x00100000, engine + VIA_REG_TRANSET);
366 writel(0x00000000, engine + VIA_REG_TRANSPACE);
367 writel(0x00333004, engine + VIA_REG_TRANSPACE);
368 writel(0x60000000, engine + VIA_REG_TRANSPACE);
369 writel(0x61000000, engine + VIA_REG_TRANSPACE);
370 writel(0x62000000, engine + VIA_REG_TRANSPACE);
371 writel(0x63000000, engine + VIA_REG_TRANSPACE);
372 writel(0x64000000, engine + VIA_REG_TRANSPACE);
373 writel(0x7D000000, engine + VIA_REG_TRANSPACE);
374
375 writel(0xFE020000, engine + VIA_REG_TRANSET);
376 writel(0x00000000, engine + VIA_REG_TRANSPACE);
377 break;
378 }
379
380 /* Enable VQ */
381 vq_start_addr = viapar->shared->vq_vram_addr;
382 vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1;
383
384 vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF);
385 vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF);
386 vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) |
387 ((vq_end_addr & 0xFF000000) >> 16);
388 vq_len = 0x53000000 | (VQ_SIZE >> 3);
389
390 switch (chip_name) {
391 case UNICHROME_K8M890:
392 case UNICHROME_P4M900:
393 vq_start_low |= 0x20000000;
394 vq_end_low |= 0x20000000;
395 vq_high |= 0x20000000;
396 vq_len |= 0x20000000;
397
398 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
399 writel(vq_high, engine + VIA_REG_CR_TRANSPACE);
400 writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE);
401 writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE);
402 writel(vq_len, engine + VIA_REG_CR_TRANSPACE);
403 writel(0x74301001, engine + VIA_REG_CR_TRANSPACE);
404 writel(0x00000000, engine + VIA_REG_CR_TRANSPACE);
405 break;
406 default:
407 writel(0x00FE0000, engine + VIA_REG_TRANSET);
408 writel(0x080003FE, engine + VIA_REG_TRANSPACE);
409 writel(0x0A00027C, engine + VIA_REG_TRANSPACE);
410 writel(0x0B000260, engine + VIA_REG_TRANSPACE);
411 writel(0x0C000274, engine + VIA_REG_TRANSPACE);
412 writel(0x0D000264, engine + VIA_REG_TRANSPACE);
413 writel(0x0E000000, engine + VIA_REG_TRANSPACE);
414 writel(0x0F000020, engine + VIA_REG_TRANSPACE);
415 writel(0x1000027E, engine + VIA_REG_TRANSPACE);
416 writel(0x110002FE, engine + VIA_REG_TRANSPACE);
417 writel(0x200F0060, engine + VIA_REG_TRANSPACE);
418
419 writel(0x00000006, engine + VIA_REG_TRANSPACE);
420 writel(0x40008C0F, engine + VIA_REG_TRANSPACE);
421 writel(0x44000000, engine + VIA_REG_TRANSPACE);
422 writel(0x45080C04, engine + VIA_REG_TRANSPACE);
423 writel(0x46800408, engine + VIA_REG_TRANSPACE);
424
425 writel(vq_high, engine + VIA_REG_TRANSPACE);
426 writel(vq_start_low, engine + VIA_REG_TRANSPACE);
427 writel(vq_end_low, engine + VIA_REG_TRANSPACE);
428 writel(vq_len, engine + VIA_REG_TRANSPACE);
429 break;
430 }
431
231 /* Set Cursor Image Base Address */ 432 /* Set Cursor Image Base Address */
232 writel(viaparinfo->cursor_start, 433 writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE);
233 viaparinfo->io_virt + VIA_REG_CURSOR_MODE); 434 writel(0x0, engine + VIA_REG_CURSOR_POS);
234 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS); 435 writel(0x0, engine + VIA_REG_CURSOR_ORG);
235 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG); 436 writel(0x0, engine + VIA_REG_CURSOR_BG);
236 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG); 437 writel(0x0, engine + VIA_REG_CURSOR_FG);
237 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG); 438 return 0;
238} 439}
239 440
240void viafb_show_hw_cursor(struct fb_info *info, int Status) 441void viafb_show_hw_cursor(struct fb_info *info, int Status)
241{ 442{
242 u32 temp; 443 struct viafb_par *viapar = info->par;
243 u32 iga_path = ((struct viafb_par *)(info->par))->iga_path; 444 u32 temp, iga_path = viapar->iga_path;
244 445
245 temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE); 446 temp = readl(viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE);
246 switch (Status) { 447 switch (Status) {
247 case HW_Cursor_ON: 448 case HW_Cursor_ON:
248 temp |= 0x1; 449 temp |= 0x1;
@@ -259,25 +460,27 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status)
259 default: 460 default:
260 temp &= 0x7FFFFFFF; 461 temp &= 0x7FFFFFFF;
261 } 462 }
262 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE); 463 writel(temp, viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE);
263} 464}
264 465
265int viafb_wait_engine_idle(void) 466void viafb_wait_engine_idle(struct fb_info *info)
266{ 467{
468 struct viafb_par *viapar = info->par;
267 int loop = 0; 469 int loop = 0;
268 470
269 while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & 471 while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) &
270 VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { 472 VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
271 loop++; 473 loop++;
272 cpu_relax(); 474 cpu_relax();
273 } 475 }
274 476
275 while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & 477 while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) &
276 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && 478 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
277 (loop < MAXLOOP)) { 479 (loop < MAXLOOP)) {
278 loop++; 480 loop++;
279 cpu_relax(); 481 cpu_relax();
280 } 482 }
281 483
282 return loop >= MAXLOOP; 484 if (loop >= MAXLOOP)
485 printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n");
283} 486}
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
index 29bf854e8ccf..615c84ad0f01 100644
--- a/drivers/video/via/accel.h
+++ b/drivers/video/via/accel.h
@@ -159,11 +159,12 @@
159 159
160#define MAXLOOP 0xFFFFFF 160#define MAXLOOP 0xFFFFFF
161 161
162void viafb_init_accel(void); 162#define VIA_BITBLT_COLOR 1
163void viafb_init_2d_engine(void); 163#define VIA_BITBLT_MONO 2
164void set_2d_color_depth(int); 164#define VIA_BITBLT_FILL 3
165void viafb_hw_cursor_init(void); 165
166void viafb_show_hw_cursor(struct fb_info *info, int Status); int 166int viafb_init_engine(struct fb_info *info);
167viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp); 167void viafb_show_hw_cursor(struct fb_info *info, int Status);
168void viafb_wait_engine_idle(struct fb_info *info);
168 169
169#endif /* __ACCEL_H__ */ 170#endif /* __ACCEL_H__ */
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index dde95edc387a..474f428aea92 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -68,6 +68,9 @@
68#define UNICHROME_VX800 11 68#define UNICHROME_VX800 11
69#define UNICHROME_VX800_DID 0x1122 69#define UNICHROME_VX800_DID 0x1122
70 70
71#define UNICHROME_VX855 12
72#define UNICHROME_VX855_DID 0x5122
73
71/**************************************************/ 74/**************************************************/
72/* Definition TMDS Trasmitter Information */ 75/* Definition TMDS Trasmitter Information */
73/**************************************************/ 76/**************************************************/
@@ -122,7 +125,6 @@ struct lvds_chip_information {
122struct chip_information { 125struct chip_information {
123 int gfx_chip_name; 126 int gfx_chip_name;
124 int gfx_chip_revision; 127 int gfx_chip_revision;
125 int chip_on_slot;
126 struct tmds_chip_information tmds_chip_info; 128 struct tmds_chip_information tmds_chip_info;
127 struct lvds_chip_information lvds_chip_info; 129 struct lvds_chip_information lvds_chip_info;
128 struct lvds_chip_information lvds_chip_info2; 130 struct lvds_chip_information lvds_chip_info2;
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index d6965447ca69..c5c32b6b6e6c 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -160,7 +160,7 @@ int viafb_tmds_trasmitter_identify(void)
160 160
161static void tmds_register_write(int index, u8 data) 161static void tmds_register_write(int index, u8 data)
162{ 162{
163 viaparinfo->i2c_stuff.i2c_port = 163 viaparinfo->shared->i2c_stuff.i2c_port =
164 viaparinfo->chip_info->tmds_chip_info.i2c_port; 164 viaparinfo->chip_info->tmds_chip_info.i2c_port;
165 165
166 viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info. 166 viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.
@@ -172,7 +172,7 @@ static int tmds_register_read(int index)
172{ 172{
173 u8 data; 173 u8 data;
174 174
175 viaparinfo->i2c_stuff.i2c_port = 175 viaparinfo->shared->i2c_stuff.i2c_port =
176 viaparinfo->chip_info->tmds_chip_info.i2c_port; 176 viaparinfo->chip_info->tmds_chip_info.i2c_port;
177 viafb_i2c_readbyte((u8) viaparinfo->chip_info-> 177 viafb_i2c_readbyte((u8) viaparinfo->chip_info->
178 tmds_chip_info.tmds_chip_slave_addr, 178 tmds_chip_info.tmds_chip_slave_addr,
@@ -182,7 +182,7 @@ static int tmds_register_read(int index)
182 182
183static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) 183static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
184{ 184{
185 viaparinfo->i2c_stuff.i2c_port = 185 viaparinfo->shared->i2c_stuff.i2c_port =
186 viaparinfo->chip_info->tmds_chip_info.i2c_port; 186 viaparinfo->chip_info->tmds_chip_info.i2c_port;
187 viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info. 187 viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info.
188 tmds_chip_slave_addr, (u8) index, buff, buff_len); 188 tmds_chip_slave_addr, (u8) index, buff, buff_len);
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index 468be2425af3..b675cdbb03ad 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -32,7 +32,6 @@ int viafb_lcd_dsp_method = LCD_EXPANDSION;
32int viafb_lcd_mode = LCD_OPENLDI; 32int viafb_lcd_mode = LCD_OPENLDI;
33int viafb_bpp = 32; 33int viafb_bpp = 32;
34int viafb_bpp1 = 32; 34int viafb_bpp1 = 32;
35int viafb_accel = 1;
36int viafb_CRT_ON = 1; 35int viafb_CRT_ON = 1;
37int viafb_DVI_ON; 36int viafb_DVI_ON;
38int viafb_LCD_ON ; 37int viafb_LCD_ON ;
@@ -46,13 +45,11 @@ int viafb_hotplug_refresh = 60;
46unsigned int viafb_second_offset; 45unsigned int viafb_second_offset;
47int viafb_second_size; 46int viafb_second_size;
48int viafb_primary_dev = None_Device; 47int viafb_primary_dev = None_Device;
49void __iomem *viafb_FB_MM;
50unsigned int viafb_second_xres = 640; 48unsigned int viafb_second_xres = 640;
51unsigned int viafb_second_yres = 480; 49unsigned int viafb_second_yres = 480;
52unsigned int viafb_second_virtual_xres; 50unsigned int viafb_second_virtual_xres;
53unsigned int viafb_second_virtual_yres; 51unsigned int viafb_second_virtual_yres;
54int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1; 52int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
55struct fb_cursor viacursor;
56struct fb_info *viafbinfo; 53struct fb_info *viafbinfo;
57struct fb_info *viafbinfo1; 54struct fb_info *viafbinfo1;
58struct viafb_par *viaparinfo; 55struct viafb_par *viaparinfo;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index 7543d5f7e309..d69d0ca99c2f 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -77,8 +77,6 @@ extern int viafb_hotplug_Yres;
77extern int viafb_hotplug_bpp; 77extern int viafb_hotplug_bpp;
78extern int viafb_hotplug_refresh; 78extern int viafb_hotplug_refresh;
79extern int viafb_primary_dev; 79extern int viafb_primary_dev;
80extern void __iomem *viafb_FB_MM;
81extern struct fb_cursor viacursor;
82 80
83extern unsigned int viafb_second_xres; 81extern unsigned int viafb_second_xres;
84extern unsigned int viafb_second_yres; 82extern unsigned int viafb_second_yres;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index fcd53ceb88fa..3e083ff67ae2 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -21,125 +21,143 @@
21 21
22#include "global.h" 22#include "global.h"
23 23
24static const struct pci_device_id_info pciidlist[] = {
25 {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266},
26 {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800},
27 {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400},
28 {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800},
29 {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700},
30 {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890},
31 {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890},
32 {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700},
33 {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900},
34 {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750},
35 {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800},
36 {0, 0, 0}
37};
38
39struct offset offset_reg = {
40 /* IGA1 Offset Register */
41 {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } },
42 /* IGA2 Offset Register */
43 {IGA2_OFFSET_REG_NUM, {{CR66, 0, 7}, {CR67, 0, 1} } }
44};
45
46static struct pll_map pll_value[] = { 24static struct pll_map pll_value[] = {
47 {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M}, 25 {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M,
48 {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M}, 26 CX700_25_175M, VX855_25_175M},
49 {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M}, 27 {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M,
50 {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M}, 28 CX700_29_581M, VX855_29_581M},
51 {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M}, 29 {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M,
52 {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M}, 30 CX700_26_880M, VX855_26_880M},
53 {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M}, 31 {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M,
54 {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M}, 32 CX700_31_490M, VX855_31_490M},
55 {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M}, 33 {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M,
56 {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M}, 34 CX700_31_500M, VX855_31_500M},
57 {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M}, 35 {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M,
58 {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M}, 36 CX700_31_728M, VX855_31_728M},
59 {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M}, 37 {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M,
60 {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M}, 38 CX700_32_668M, VX855_32_668M},
61 {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M}, 39 {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M,
62 {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M}, 40 CX700_36_000M, VX855_36_000M},
63 {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M}, 41 {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M,
64 {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M}, 42 CX700_40_000M, VX855_40_000M},
65 {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M}, 43 {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M,
66 {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M}, 44 CX700_41_291M, VX855_41_291M},
67 {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M}, 45 {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M,
68 {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M}, 46 CX700_43_163M, VX855_43_163M},
69 {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M}, 47 {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M,
70 {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M}, 48 CX700_45_250M, VX855_45_250M},
71 {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M}, 49 {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M,
72 {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M}, 50 CX700_46_000M, VX855_46_000M},
73 {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M}, 51 {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M,
74 {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M}, 52 CX700_46_996M, VX855_46_996M},
75 {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M}, 53 {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M,
76 {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M}, 54 CX700_48_000M, VX855_48_000M},
77 {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M}, 55 {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M,
78 {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M}, 56 CX700_48_875M, VX855_48_875M},
79 {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M}, 57 {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M,
80 {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M}, 58 CX700_49_500M, VX855_49_500M},
81 {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M}, 59 {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M,
82 {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M}, 60 CX700_52_406M, VX855_52_406M},
83 {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M}, 61 {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M,
84 {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M}, 62 CX700_52_977M, VX855_52_977M},
63 {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M,
64 CX700_56_250M, VX855_56_250M},
65 {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M,
66 CX700_60_466M, VX855_60_466M},
67 {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M,
68 CX700_61_500M, VX855_61_500M},
69 {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M,
70 CX700_65_000M, VX855_65_000M},
71 {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M,
72 CX700_65_178M, VX855_65_178M},
73 {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M,
74 CX700_66_750M, VX855_66_750M},
75 {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M,
76 CX700_68_179M, VX855_68_179M},
77 {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M,
78 CX700_69_924M, VX855_69_924M},
79 {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M,
80 CX700_70_159M, VX855_70_159M},
81 {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M,
82 CX700_72_000M, VX855_72_000M},
83 {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M,
84 CX700_78_750M, VX855_78_750M},
85 {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M,
86 CX700_80_136M, VX855_80_136M},
87 {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M,
88 CX700_83_375M, VX855_83_375M},
89 {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M,
90 CX700_83_950M, VX855_83_950M},
91 {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M,
92 CX700_84_750M, VX855_84_750M},
93 {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M,
94 CX700_85_860M, VX855_85_860M},
95 {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M,
96 CX700_88_750M, VX855_88_750M},
97 {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M,
98 CX700_94_500M, VX855_94_500M},
99 {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M,
100 CX700_97_750M, VX855_97_750M},
85 {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M, 101 {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M,
86 CX700_101_000M}, 102 CX700_101_000M, VX855_101_000M},
87 {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M, 103 {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M,
88 CX700_106_500M}, 104 CX700_106_500M, VX855_106_500M},
89 {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M, 105 {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M,
90 CX700_108_000M}, 106 CX700_108_000M, VX855_108_000M},
91 {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M, 107 {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M,
92 CX700_113_309M}, 108 CX700_113_309M, VX855_113_309M},
93 {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M, 109 {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M,
94 CX700_118_840M}, 110 CX700_118_840M, VX855_118_840M},
95 {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M, 111 {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M,
96 CX700_119_000M}, 112 CX700_119_000M, VX855_119_000M},
97 {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M, 113 {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M,
98 CX700_121_750M}, 114 CX700_121_750M, 0},
99 {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M, 115 {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M,
100 CX700_125_104M}, 116 CX700_125_104M, 0},
101 {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M, 117 {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M,
102 CX700_133_308M}, 118 CX700_133_308M, 0},
103 {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M, 119 {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M,
104 CX700_135_000M}, 120 CX700_135_000M, VX855_135_000M},
105 {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M, 121 {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M,
106 CX700_136_700M}, 122 CX700_136_700M, VX855_136_700M},
107 {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M, 123 {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M,
108 CX700_138_400M}, 124 CX700_138_400M, VX855_138_400M},
109 {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M, 125 {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M,
110 CX700_146_760M}, 126 CX700_146_760M, VX855_146_760M},
111 {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M, 127 {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M,
112 CX700_153_920M}, 128 CX700_153_920M, VX855_153_920M},
113 {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M, 129 {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M,
114 CX700_156_000M}, 130 CX700_156_000M, VX855_156_000M},
115 {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M, 131 {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M,
116 CX700_157_500M}, 132 CX700_157_500M, VX855_157_500M},
117 {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M, 133 {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M,
118 CX700_162_000M}, 134 CX700_162_000M, VX855_162_000M},
119 {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M, 135 {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M,
120 CX700_187_000M}, 136 CX700_187_000M, VX855_187_000M},
121 {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M, 137 {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M,
122 CX700_193_295M}, 138 CX700_193_295M, VX855_193_295M},
123 {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M, 139 {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M,
124 CX700_202_500M}, 140 CX700_202_500M, VX855_202_500M},
125 {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M, 141 {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M,
126 CX700_204_000M}, 142 CX700_204_000M, VX855_204_000M},
127 {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M, 143 {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M,
128 CX700_218_500M}, 144 CX700_218_500M, VX855_218_500M},
129 {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M, 145 {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M,
130 CX700_234_000M}, 146 CX700_234_000M, VX855_234_000M},
131 {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M, 147 {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M,
132 CX700_267_250M}, 148 CX700_267_250M, VX855_267_250M},
133 {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M, 149 {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M,
134 CX700_297_500M}, 150 CX700_297_500M, VX855_297_500M},
135 {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M}, 151 {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M,
152 CX700_74_481M, VX855_74_481M},
136 {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M, 153 {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M,
137 CX700_172_798M}, 154 CX700_172_798M, VX855_172_798M},
138 {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M, 155 {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M,
139 CX700_122_614M}, 156 CX700_122_614M, VX855_122_614M},
140 {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M}, 157 {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M,
158 CX700_74_270M, 0},
141 {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M, 159 {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M,
142 CX700_148_500M} 160 CX700_148_500M, VX855_148_500M}
143}; 161};
144 162
145static struct fifo_depth_select display_fifo_depth_reg = { 163static struct fifo_depth_select display_fifo_depth_reg = {
@@ -508,7 +526,8 @@ static void set_dvi_output_path(int set_iga, int output_interface);
508static void set_lcd_output_path(int set_iga, int output_interface); 526static void set_lcd_output_path(int set_iga, int output_interface);
509static int search_mode_setting(int ModeInfoIndex); 527static int search_mode_setting(int ModeInfoIndex);
510static void load_fix_bit_crtc_reg(void); 528static void load_fix_bit_crtc_reg(void);
511static void init_gfx_chip_info(void); 529static void init_gfx_chip_info(struct pci_dev *pdev,
530 const struct pci_device_id *pdi);
512static void init_tmds_chip_info(void); 531static void init_tmds_chip_info(void);
513static void init_lvds_chip_info(void); 532static void init_lvds_chip_info(void);
514static void device_screen_off(void); 533static void device_screen_off(void);
@@ -518,7 +537,6 @@ static void device_off(void);
518static void device_on(void); 537static void device_on(void);
519static void enable_second_display_channel(void); 538static void enable_second_display_channel(void);
520static void disable_second_display_channel(void); 539static void disable_second_display_channel(void);
521static int get_fb_size_from_pci(void);
522 540
523void viafb_write_reg(u8 index, u16 io_port, u8 data) 541void viafb_write_reg(u8 index, u16 io_port, u8 data)
524{ 542{
@@ -629,70 +647,43 @@ void viafb_set_iga_path(void)
629 } 647 }
630} 648}
631 649
632void viafb_set_start_addr(void) 650void viafb_set_primary_address(u32 addr)
633{ 651{
634 unsigned long offset = 0, tmp = 0, size = 0; 652 DEBUG_MSG(KERN_DEBUG "viafb_set_primary_address(0x%08X)\n", addr);
635 unsigned long length; 653 viafb_write_reg(CR0D, VIACR, addr & 0xFF);
636 654 viafb_write_reg(CR0C, VIACR, (addr >> 8) & 0xFF);
637 DEBUG_MSG(KERN_INFO "viafb_set_start_addr!\n"); 655 viafb_write_reg(CR34, VIACR, (addr >> 16) & 0xFF);
638 viafb_unlock_crt(); 656 viafb_write_reg_mask(CR48, VIACR, (addr >> 24) & 0x1F, 0x1F);
639 /* update starting address of IGA1 */ 657}
640 viafb_write_reg(CR0C, VIACR, 0x00); /*initial starting address */
641 viafb_write_reg(CR0D, VIACR, 0x00);
642 viafb_write_reg(CR34, VIACR, 0x00);
643 viafb_write_reg_mask(CR48, VIACR, 0x00, 0x1F);
644
645 if (viafb_dual_fb) {
646 viaparinfo->iga_path = IGA1;
647 viaparinfo1->iga_path = IGA2;
648 }
649
650 if (viafb_SAMM_ON == 1) {
651 if (!viafb_dual_fb) {
652 if (viafb_second_size)
653 size = viafb_second_size * 1024 * 1024;
654 else
655 size = 8 * 1024 * 1024;
656 } else {
657 658
658 size = viaparinfo1->memsize; 659void viafb_set_secondary_address(u32 addr)
659 } 660{
660 offset = viafb_second_offset; 661 DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_address(0x%08X)\n", addr);
661 DEBUG_MSG(KERN_INFO 662 /* secondary display supports only quadword aligned memory */
662 "viafb_second_size=%lx, second start_adddress=%lx\n", 663 viafb_write_reg_mask(CR62, VIACR, (addr >> 2) & 0xFE, 0xFE);
663 size, offset); 664 viafb_write_reg(CR63, VIACR, (addr >> 10) & 0xFF);
664 } 665 viafb_write_reg(CR64, VIACR, (addr >> 18) & 0xFF);
665 if (viafb_SAMM_ON == 1) { 666 viafb_write_reg_mask(CRA3, VIACR, (addr >> 26) & 0x07, 0x07);
666 offset = offset >> 3; 667}
667
668 tmp = viafb_read_reg(VIACR, 0x62) & 0x01;
669 tmp |= (offset & 0x7F) << 1;
670 viafb_write_reg(CR62, VIACR, tmp);
671 viafb_write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7));
672 viafb_write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15));
673 viafb_write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23));
674 } else {
675 /* update starting address */
676 viafb_write_reg(CR62, VIACR, 0x00);
677 viafb_write_reg(CR63, VIACR, 0x00);
678 viafb_write_reg(CR64, VIACR, 0x00);
679 viafb_write_reg(CRA3, VIACR, 0x00);
680 }
681 668
682 if (viafb_SAMM_ON == 1) { 669void viafb_set_primary_pitch(u32 pitch)
683 if (viafb_accel) { 670{
684 if (!viafb_dual_fb) 671 DEBUG_MSG(KERN_DEBUG "viafb_set_primary_pitch(0x%08X)\n", pitch);
685 length = size - viaparinfo->fbmem_used; 672 /* spec does not say that first adapter skips 3 bits but old
686 else 673 * code did it and seems to be reasonable in analogy to 2nd adapter
687 length = size - viaparinfo1->fbmem_used; 674 */
688 } else 675 pitch = pitch >> 3;
689 length = size; 676 viafb_write_reg(0x13, VIACR, pitch & 0xFF);
690 offset = (unsigned long)(void *)viafb_FB_MM + 677 viafb_write_reg_mask(0x35, VIACR, (pitch >> (8 - 5)) & 0xE0, 0xE0);
691 viafb_second_offset; 678}
692 memset((void *)offset, 0, length);
693 }
694 679
695 viafb_lock_crt(); 680void viafb_set_secondary_pitch(u32 pitch)
681{
682 DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_pitch(0x%08X)\n", pitch);
683 pitch = pitch >> 3;
684 viafb_write_reg(0x66, VIACR, pitch & 0xFF);
685 viafb_write_reg_mask(0x67, VIACR, (pitch >> 8) & 0x03, 0x03);
686 viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80);
696} 687}
697 688
698void viafb_set_output_path(int device, int set_iga, int output_interface) 689void viafb_set_output_path(int device, int set_iga, int output_interface)
@@ -1123,30 +1114,6 @@ void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1123 } 1114 }
1124} 1115}
1125 1116
1126void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga)
1127{
1128 int reg_value;
1129 int viafb_load_reg_num;
1130 struct io_register *reg;
1131
1132 switch (set_iga) {
1133 case IGA1_IGA2:
1134 case IGA1:
1135 reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte);
1136 viafb_load_reg_num = offset_reg.iga1_offset_reg.reg_num;
1137 reg = offset_reg.iga1_offset_reg.reg;
1138 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1139 if (set_iga == IGA1)
1140 break;
1141 case IGA2:
1142 reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte);
1143 viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
1144 reg = offset_reg.iga2_offset_reg.reg;
1145 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1146 break;
1147 }
1148}
1149
1150void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) 1117void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1151{ 1118{
1152 int reg_value; 1119 int reg_value;
@@ -1277,6 +1244,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1277 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; 1244 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1278 } 1245 }
1279 1246
1247 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1248 iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
1249 iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
1250 iga1_fifo_high_threshold =
1251 VX855_IGA1_FIFO_HIGH_THRESHOLD;
1252 iga1_display_queue_expire_num =
1253 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1254 }
1255
1280 /* Set Display FIFO Depath Select */ 1256 /* Set Display FIFO Depath Select */
1281 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); 1257 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1282 viafb_load_reg_num = 1258 viafb_load_reg_num =
@@ -1408,6 +1384,15 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1408 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; 1384 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1409 } 1385 }
1410 1386
1387 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1388 iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
1389 iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
1390 iga2_fifo_high_threshold =
1391 VX855_IGA2_FIFO_HIGH_THRESHOLD;
1392 iga2_display_queue_expire_num =
1393 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1394 }
1395
1411 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { 1396 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1412 /* Set Display FIFO Depath Select */ 1397 /* Set Display FIFO Depath Select */
1413 reg_value = 1398 reg_value =
@@ -1496,6 +1481,8 @@ u32 viafb_get_clk_value(int clk)
1496 case UNICHROME_P4M900: 1481 case UNICHROME_P4M900:
1497 case UNICHROME_VX800: 1482 case UNICHROME_VX800:
1498 return pll_value[i].cx700_pll; 1483 return pll_value[i].cx700_pll;
1484 case UNICHROME_VX855:
1485 return pll_value[i].vx855_pll;
1499 } 1486 }
1500 } 1487 }
1501 } 1488 }
@@ -1529,6 +1516,7 @@ void viafb_set_vclock(u32 CLK, int set_iga)
1529 case UNICHROME_P4M890: 1516 case UNICHROME_P4M890:
1530 case UNICHROME_P4M900: 1517 case UNICHROME_P4M900:
1531 case UNICHROME_VX800: 1518 case UNICHROME_VX800:
1519 case UNICHROME_VX855:
1532 viafb_write_reg(SR44, VIASR, CLK / 0x10000); 1520 viafb_write_reg(SR44, VIASR, CLK / 0x10000);
1533 DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000); 1521 DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000);
1534 viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100); 1522 viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100);
@@ -1557,6 +1545,7 @@ void viafb_set_vclock(u32 CLK, int set_iga)
1557 case UNICHROME_P4M890: 1545 case UNICHROME_P4M890:
1558 case UNICHROME_P4M900: 1546 case UNICHROME_P4M900:
1559 case UNICHROME_VX800: 1547 case UNICHROME_VX800:
1548 case UNICHROME_VX855:
1560 viafb_write_reg(SR4A, VIASR, CLK / 0x10000); 1549 viafb_write_reg(SR4A, VIASR, CLK / 0x10000);
1561 viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100); 1550 viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100);
1562 viafb_write_reg(SR4C, VIASR, CLK % 0x100); 1551 viafb_write_reg(SR4C, VIASR, CLK % 0x100);
@@ -1916,7 +1905,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1916 load_fix_bit_crtc_reg(); 1905 load_fix_bit_crtc_reg();
1917 viafb_lock_crt(); 1906 viafb_lock_crt();
1918 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); 1907 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1919 viafb_load_offset_reg(h_addr, bpp_byte, set_iga);
1920 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); 1908 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
1921 1909
1922 /* load FIFO */ 1910 /* load FIFO */
@@ -1933,9 +1921,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1933 1921
1934} 1922}
1935 1923
1936void viafb_init_chip_info(void) 1924void viafb_init_chip_info(struct pci_dev *pdev,
1925 const struct pci_device_id *pdi)
1937{ 1926{
1938 init_gfx_chip_info(); 1927 init_gfx_chip_info(pdev, pdi);
1939 init_tmds_chip_info(); 1928 init_tmds_chip_info();
1940 init_lvds_chip_info(); 1929 init_lvds_chip_info();
1941 1930
@@ -2008,24 +1997,12 @@ void viafb_update_device_setting(int hres, int vres,
2008 } 1997 }
2009} 1998}
2010 1999
2011static void init_gfx_chip_info(void) 2000static void init_gfx_chip_info(struct pci_dev *pdev,
2001 const struct pci_device_id *pdi)
2012{ 2002{
2013 struct pci_dev *pdev = NULL;
2014 u32 i;
2015 u8 tmp; 2003 u8 tmp;
2016 2004
2017 /* Indentify GFX Chip Name */ 2005 viaparinfo->chip_info->gfx_chip_name = pdi->driver_data;
2018 for (i = 0; pciidlist[i].vendor != 0; i++) {
2019 pdev = pci_get_device(pciidlist[i].vendor,
2020 pciidlist[i].device, 0);
2021 if (pdev)
2022 break;
2023 }
2024
2025 if (!pciidlist[i].vendor)
2026 return ;
2027
2028 viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index;
2029 2006
2030 /* Check revision of CLE266 Chip */ 2007 /* Check revision of CLE266 Chip */
2031 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 2008 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
@@ -2056,8 +2033,6 @@ static void init_gfx_chip_info(void)
2056 CX700_REVISION_700; 2033 CX700_REVISION_700;
2057 } 2034 }
2058 } 2035 }
2059
2060 pci_dev_put(pdev);
2061} 2036}
2062 2037
2063static void init_tmds_chip_info(void) 2038static void init_tmds_chip_info(void)
@@ -2271,11 +2246,12 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2271 break; 2246 break;
2272 2247
2273 case UNICHROME_CX700: 2248 case UNICHROME_CX700:
2274 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
2275
2276 case UNICHROME_VX800: 2249 case UNICHROME_VX800:
2277 viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs); 2250 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
2251 break;
2278 2252
2253 case UNICHROME_VX855:
2254 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
2279 break; 2255 break;
2280 } 2256 }
2281 2257
@@ -2291,7 +2267,8 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2291 outb(VPIT.SR[i - 1], VIASR + 1); 2267 outb(VPIT.SR[i - 1], VIASR + 1);
2292 } 2268 }
2293 2269
2294 viafb_set_start_addr(); 2270 viafb_set_primary_address(0);
2271 viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
2295 viafb_set_iga_path(); 2272 viafb_set_iga_path();
2296 2273
2297 /* Write CRTC */ 2274 /* Write CRTC */
@@ -2371,6 +2348,9 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2371 } 2348 }
2372 } 2349 }
2373 2350
2351 viafb_set_primary_pitch(viafbinfo->fix.line_length);
2352 viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
2353 : viafbinfo->fix.line_length);
2374 /* Update Refresh Rate Setting */ 2354 /* Update Refresh Rate Setting */
2375 2355
2376 /* Clear On Screen */ 2356 /* Clear On Screen */
@@ -2407,14 +2387,14 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2407 viafb_dvi_set_mode(viafb_get_mode_index 2387 viafb_dvi_set_mode(viafb_get_mode_index
2408 (viaparinfo->tmds_setting_info->h_active, 2388 (viaparinfo->tmds_setting_info->h_active,
2409 viaparinfo->tmds_setting_info-> 2389 viaparinfo->tmds_setting_info->
2410 v_active, 1), 2390 v_active),
2411 video_bpp1, viaparinfo-> 2391 video_bpp1, viaparinfo->
2412 tmds_setting_info->iga_path); 2392 tmds_setting_info->iga_path);
2413 } else { 2393 } else {
2414 viafb_dvi_set_mode(viafb_get_mode_index 2394 viafb_dvi_set_mode(viafb_get_mode_index
2415 (viaparinfo->tmds_setting_info->h_active, 2395 (viaparinfo->tmds_setting_info->h_active,
2416 viaparinfo-> 2396 viaparinfo->
2417 tmds_setting_info->v_active, 0), 2397 tmds_setting_info->v_active),
2418 video_bpp, viaparinfo-> 2398 video_bpp, viaparinfo->
2419 tmds_setting_info->iga_path); 2399 tmds_setting_info->iga_path);
2420 } 2400 }
@@ -2545,38 +2525,6 @@ void viafb_crt_enable(void)
2545 viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4); 2525 viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
2546} 2526}
2547 2527
2548void viafb_get_mmio_info(unsigned long *mmio_base,
2549 unsigned long *mmio_len)
2550{
2551 struct pci_dev *pdev = NULL;
2552 u32 vendor, device;
2553 u32 i;
2554
2555 for (i = 0; pciidlist[i].vendor != 0; i++)
2556 if (viaparinfo->chip_info->gfx_chip_name ==
2557 pciidlist[i].chip_index)
2558 break;
2559
2560 if (!pciidlist[i].vendor)
2561 return ;
2562
2563 vendor = pciidlist[i].vendor;
2564 device = pciidlist[i].device;
2565
2566 pdev = pci_get_device(vendor, device, NULL);
2567
2568 if (!pdev) {
2569 *mmio_base = 0;
2570 *mmio_len = 0;
2571 return ;
2572 }
2573
2574 *mmio_base = pci_resource_start(pdev, 1);
2575 *mmio_len = pci_resource_len(pdev, 1);
2576
2577 pci_dev_put(pdev);
2578}
2579
2580static void enable_second_display_channel(void) 2528static void enable_second_display_channel(void)
2581{ 2529{
2582 /* to enable second display channel. */ 2530 /* to enable second display channel. */
@@ -2593,44 +2541,7 @@ static void disable_second_display_channel(void)
2593 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); 2541 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2594} 2542}
2595 2543
2596void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len) 2544int viafb_get_fb_size_from_pci(void)
2597{
2598 struct pci_dev *pdev = NULL;
2599 u32 vendor, device;
2600 u32 i;
2601
2602 for (i = 0; pciidlist[i].vendor != 0; i++)
2603 if (viaparinfo->chip_info->gfx_chip_name ==
2604 pciidlist[i].chip_index)
2605 break;
2606
2607 if (!pciidlist[i].vendor)
2608 return ;
2609
2610 vendor = pciidlist[i].vendor;
2611 device = pciidlist[i].device;
2612
2613 pdev = pci_get_device(vendor, device, NULL);
2614
2615 if (!pdev) {
2616 *fb_base = viafb_read_reg(VIASR, SR30) << 24;
2617 *fb_len = viafb_get_memsize();
2618 DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n");
2619 DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
2620 DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
2621 return ;
2622 }
2623
2624 *fb_base = (unsigned int)pci_resource_start(pdev, 0);
2625 *fb_len = get_fb_size_from_pci();
2626 DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n");
2627 DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
2628 DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
2629
2630 pci_dev_put(pdev);
2631}
2632
2633static int get_fb_size_from_pci(void)
2634{ 2545{
2635 unsigned long configid, deviceid, FBSize = 0; 2546 unsigned long configid, deviceid, FBSize = 0;
2636 int VideoMemSize; 2547 int VideoMemSize;
@@ -2656,6 +2567,7 @@ static int get_fb_size_from_pci(void)
2656 case P4M890_FUNCTION3: 2567 case P4M890_FUNCTION3:
2657 case P4M900_FUNCTION3: 2568 case P4M900_FUNCTION3:
2658 case VX800_FUNCTION3: 2569 case VX800_FUNCTION3:
2570 case VX855_FUNCTION3:
2659 /*case CN750_FUNCTION3: */ 2571 /*case CN750_FUNCTION3: */
2660 outl(configid + 0xA0, (unsigned long)0xCF8); 2572 outl(configid + 0xA0, (unsigned long)0xCF8);
2661 FBSize = inl((unsigned long)0xCFC); 2573 FBSize = inl((unsigned long)0xCFC);
@@ -2719,6 +2631,10 @@ static int get_fb_size_from_pci(void)
2719 VideoMemSize = (256 << 20); /*256M */ 2631 VideoMemSize = (256 << 20); /*256M */
2720 break; 2632 break;
2721 2633
2634 case 0x00007000: /* Only on VX855/875 */
2635 VideoMemSize = (512 << 20); /*512M */
2636 break;
2637
2722 default: 2638 default:
2723 VideoMemSize = (32 << 20); /*32M */ 2639 VideoMemSize = (32 << 20); /*32M */
2724 break; 2640 break;
@@ -2788,24 +2704,6 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2788 } 2704 }
2789} 2705}
2790 2706
2791void viafb_memory_pitch_patch(struct fb_info *info)
2792{
2793 if (info->var.xres != info->var.xres_virtual) {
2794 viafb_load_offset_reg(info->var.xres_virtual,
2795 info->var.bits_per_pixel >> 3, IGA1);
2796
2797 if (viafb_SAMM_ON) {
2798 viafb_load_offset_reg(viafb_second_virtual_xres,
2799 viafb_bpp1 >> 3,
2800 IGA2);
2801 } else {
2802 viafb_load_offset_reg(info->var.xres_virtual,
2803 info->var.bits_per_pixel >> 3, IGA2);
2804 }
2805
2806 }
2807}
2808
2809/*According var's xres, yres fill var's other timing information*/ 2707/*According var's xres, yres fill var's other timing information*/
2810void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 2708void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2811 int mode_index) 2709 int mode_index)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 6ff38fa8569a..b874d952b446 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -147,14 +147,8 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
147/* location: {CR5F,0,4} */ 147/* location: {CR5F,0,4} */
148#define IGA2_VER_SYNC_END_REG_NUM 1 148#define IGA2_VER_SYNC_END_REG_NUM 1
149 149
150/* Define Offset and Fetch Count Register*/ 150/* Define Fetch Count Register*/
151 151
152/* location: {CR13,0,7},{CR35,5,7} */
153#define IGA1_OFFSET_REG_NUM 2
154/* 8 bytes alignment. */
155#define IGA1_OFFSER_ALIGN_BYTE 8
156/* x: H resolution, y: color depth */
157#define IGA1_OFFSET_FORMULA(x, y) ((x*y)/IGA1_OFFSER_ALIGN_BYTE)
158/* location: {SR1C,0,7},{SR1D,0,1} */ 152/* location: {SR1C,0,7},{SR1D,0,1} */
159#define IGA1_FETCH_COUNT_REG_NUM 2 153#define IGA1_FETCH_COUNT_REG_NUM 2
160/* 16 bytes alignment. */ 154/* 16 bytes alignment. */
@@ -164,11 +158,6 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
164#define IGA1_FETCH_COUNT_FORMULA(x, y) \ 158#define IGA1_FETCH_COUNT_FORMULA(x, y) \
165 (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE) 159 (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
166 160
167/* location: {CR66,0,7},{CR67,0,1} */
168#define IGA2_OFFSET_REG_NUM 2
169#define IGA2_OFFSET_ALIGN_BYTE 8
170/* x: H resolution, y: color depth */
171#define IGA2_OFFSET_FORMULA(x, y) ((x*y)/IGA2_OFFSET_ALIGN_BYTE)
172/* location: {CR65,0,7},{CR67,2,3} */ 161/* location: {CR65,0,7},{CR67,2,3} */
173#define IGA2_FETCH_COUNT_REG_NUM 2 162#define IGA2_FETCH_COUNT_REG_NUM 2
174#define IGA2_FETCH_COUNT_ALIGN_BYTE 16 163#define IGA2_FETCH_COUNT_ALIGN_BYTE 16
@@ -335,6 +324,17 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
335/* location: {CR94,0,6} */ 324/* location: {CR94,0,6} */
336#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128 325#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
337 326
327/* For VT3409 */
328#define VX855_IGA1_FIFO_MAX_DEPTH 400
329#define VX855_IGA1_FIFO_THRESHOLD 320
330#define VX855_IGA1_FIFO_HIGH_THRESHOLD 320
331#define VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 160
332
333#define VX855_IGA2_FIFO_MAX_DEPTH 200
334#define VX855_IGA2_FIFO_THRESHOLD 160
335#define VX855_IGA2_FIFO_HIGH_THRESHOLD 160
336#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320
337
338#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1 338#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1
339#define IGA1_FIFO_THRESHOLD_REG_NUM 2 339#define IGA1_FIFO_THRESHOLD_REG_NUM 2
340#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2 340#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2
@@ -617,23 +617,6 @@ struct iga2_ver_sync_end {
617 struct io_register reg[IGA2_VER_SYNC_END_REG_NUM]; 617 struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
618}; 618};
619 619
620/* IGA1 Offset Register */
621struct iga1_offset {
622 int reg_num;
623 struct io_register reg[IGA1_OFFSET_REG_NUM];
624};
625
626/* IGA2 Offset Register */
627struct iga2_offset {
628 int reg_num;
629 struct io_register reg[IGA2_OFFSET_REG_NUM];
630};
631
632struct offset {
633 struct iga1_offset iga1_offset_reg;
634 struct iga2_offset iga2_offset_reg;
635};
636
637/* IGA1 Fetch Count Register */ 620/* IGA1 Fetch Count Register */
638struct iga1_fetch_count { 621struct iga1_fetch_count {
639 int reg_num; 622 int reg_num;
@@ -716,6 +699,7 @@ struct pll_map {
716 u32 cle266_pll; 699 u32 cle266_pll;
717 u32 k800_pll; 700 u32 k800_pll;
718 u32 cx700_pll; 701 u32 cx700_pll;
702 u32 vx855_pll;
719}; 703};
720 704
721struct rgbLUT { 705struct rgbLUT {
@@ -860,6 +844,8 @@ struct iga2_crtc_timing {
860#define P4M900_FUNCTION3 0x3364 844#define P4M900_FUNCTION3 0x3364
861/* VT3353 chipset*/ 845/* VT3353 chipset*/
862#define VX800_FUNCTION3 0x3353 846#define VX800_FUNCTION3 0x3353
847/* VT3409 chipset*/
848#define VX855_FUNCTION3 0x3409
863 849
864#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value) 850#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value)
865 851
@@ -883,7 +869,6 @@ extern int viafb_dual_fb;
883extern int viafb_LCD2_ON; 869extern int viafb_LCD2_ON;
884extern int viafb_LCD_ON; 870extern int viafb_LCD_ON;
885extern int viafb_DVI_ON; 871extern int viafb_DVI_ON;
886extern int viafb_accel;
887extern int viafb_hotplug; 872extern int viafb_hotplug;
888 873
889void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); 874void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
@@ -904,7 +889,6 @@ void viafb_write_reg(u8 index, u16 io_port, u8 data);
904u8 viafb_read_reg(int io_port, u8 index); 889u8 viafb_read_reg(int io_port, u8 index);
905void viafb_lock_crt(void); 890void viafb_lock_crt(void);
906void viafb_unlock_crt(void); 891void viafb_unlock_crt(void);
907void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga);
908void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); 892void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
909void viafb_write_regx(struct io_reg RegTable[], int ItemNum); 893void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
910struct VideoModeTable *viafb_get_modetbl_pointer(int Index); 894struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
@@ -917,17 +901,20 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
917int viafb_setmode(int vmode_index, int hor_res, int ver_res, 901int viafb_setmode(int vmode_index, int hor_res, int ver_res,
918 int video_bpp, int vmode_index1, int hor_res1, 902 int video_bpp, int vmode_index1, int hor_res1,
919 int ver_res1, int video_bpp1); 903 int ver_res1, int video_bpp1);
920void viafb_init_chip_info(void); 904void viafb_init_chip_info(struct pci_dev *pdev,
905 const struct pci_device_id *pdi);
921void viafb_init_dac(int set_iga); 906void viafb_init_dac(int set_iga);
922int viafb_get_pixclock(int hres, int vres, int vmode_refresh); 907int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
923int viafb_get_refresh(int hres, int vres, u32 float_refresh); 908int viafb_get_refresh(int hres, int vres, u32 float_refresh);
924void viafb_update_device_setting(int hres, int vres, int bpp, 909void viafb_update_device_setting(int hres, int vres, int bpp,
925 int vmode_refresh, int flag); 910 int vmode_refresh, int flag);
926void viafb_get_mmio_info(unsigned long *mmio_base,
927 unsigned long *mmio_len);
928 911
912int viafb_get_fb_size_from_pci(void);
929void viafb_set_iga_path(void); 913void viafb_set_iga_path(void);
930void viafb_set_start_addr(void); 914void viafb_set_primary_address(u32 addr);
915void viafb_set_secondary_address(u32 addr);
916void viafb_set_primary_pitch(u32 pitch);
917void viafb_set_secondary_pitch(u32 pitch);
931void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); 918void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
932 919
933#endif /* __HW_H__ */ 920#endif /* __HW_H__ */
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h
index 842fe30b9868..de899807eade 100644
--- a/drivers/video/via/ioctl.h
+++ b/drivers/video/via/ioctl.h
@@ -50,8 +50,6 @@
50#define VIAFB_GET_GAMMA_LUT 0x56494124 50#define VIAFB_GET_GAMMA_LUT 0x56494124
51#define VIAFB_SET_GAMMA_LUT 0x56494125 51#define VIAFB_SET_GAMMA_LUT 0x56494125
52#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126 52#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126
53#define VIAFB_SET_VIDEO_DEVICE 0x56494127
54#define VIAFB_GET_VIDEO_DEVICE 0x56494128
55#define VIAFB_SET_SECOND_MODE 0x56494129 53#define VIAFB_SET_SECOND_MODE 0x56494129
56#define VIAFB_SYNC_SURFACE 0x56494130 54#define VIAFB_SYNC_SURFACE 0x56494130
57#define VIAFB_GET_DRIVER_CAPS 0x56494131 55#define VIAFB_GET_DRIVER_CAPS 0x56494131
@@ -179,9 +177,7 @@ struct viafb_ioctl_setting {
179 unsigned short second_dev_bpp; 177 unsigned short second_dev_bpp;
180 /* Indicate which device are primary display device. */ 178 /* Indicate which device are primary display device. */
181 unsigned int primary_device; 179 unsigned int primary_device;
182 /* Indicate which device will show video. only valid in duoview mode */ 180 unsigned int struct_reserved[35];
183 unsigned int video_device_status;
184 unsigned int struct_reserved[34];
185 struct viafb_ioctl_lcd_attribute lcd_attributes; 181 struct viafb_ioctl_lcd_attribute lcd_attributes;
186}; 182};
187 183
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 6c7290a6a447..e3e597f937a5 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -207,13 +207,13 @@ static bool lvds_identify_integratedlvds(void)
207 207
208int viafb_lvds_trasmitter_identify(void) 208int viafb_lvds_trasmitter_identify(void)
209{ 209{
210 viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX; 210 viaparinfo->shared->i2c_stuff.i2c_port = I2CPORTINDEX;
211 if (viafb_lvds_identify_vt1636()) { 211 if (viafb_lvds_identify_vt1636()) {
212 viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX; 212 viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
213 DEBUG_MSG(KERN_INFO 213 DEBUG_MSG(KERN_INFO
214 "Found VIA VT1636 LVDS on port i2c 0x31 \n"); 214 "Found VIA VT1636 LVDS on port i2c 0x31 \n");
215 } else { 215 } else {
216 viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX; 216 viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX;
217 if (viafb_lvds_identify_vt1636()) { 217 if (viafb_lvds_identify_vt1636()) {
218 viaparinfo->chip_info->lvds_chip_info.i2c_port = 218 viaparinfo->chip_info->lvds_chip_info.i2c_port =
219 GPIOPORTINDEX; 219 GPIOPORTINDEX;
@@ -470,7 +470,7 @@ static int lvds_register_read(int index)
470{ 470{
471 u8 data; 471 u8 data;
472 472
473 viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX; 473 viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX;
474 viafb_i2c_readbyte((u8) viaparinfo->chip_info-> 474 viafb_i2c_readbyte((u8) viaparinfo->chip_info->
475 lvds_chip_info.lvds_chip_slave_addr, 475 lvds_chip_info.lvds_chip_slave_addr,
476 (u8) index, &data); 476 (u8) index, &data);
@@ -580,10 +580,7 @@ static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
580 int reg_num = 0; 580 int reg_num = 0;
581 struct io_reg *lcd_patch_reg = NULL; 581 struct io_reg *lcd_patch_reg = NULL;
582 582
583 if (viaparinfo->lvds_setting_info->iga_path == IGA2) 583 vmode_index = viafb_get_mode_index(set_hres, set_vres);
584 vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
585 else
586 vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
587 switch (panel_id) { 584 switch (panel_id) {
588 /* LCD 800x600 */ 585 /* LCD 800x600 */
589 case LCD_PANEL_ID1_800X600: 586 case LCD_PANEL_ID1_800X600:
@@ -761,10 +758,7 @@ static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
761 int reg_num = 0; 758 int reg_num = 0;
762 struct io_reg *lcd_patch_reg = NULL; 759 struct io_reg *lcd_patch_reg = NULL;
763 760
764 if (viaparinfo->lvds_setting_info->iga_path == IGA2) 761 vmode_index = viafb_get_mode_index(set_hres, set_vres);
765 vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
766 else
767 vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
768 762
769 switch (panel_id) { 763 switch (panel_id) {
770 case LCD_PANEL_ID5_1400X1050: 764 case LCD_PANEL_ID5_1400X1050:
@@ -832,10 +826,7 @@ static void load_lcd_patch_regs(int set_hres, int set_vres,
832{ 826{
833 int vmode_index; 827 int vmode_index;
834 828
835 if (viaparinfo->lvds_setting_info->iga_path == IGA2) 829 vmode_index = viafb_get_mode_index(set_hres, set_vres);
836 vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
837 else
838 vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
839 830
840 viafb_unlock_crt(); 831 viafb_unlock_crt();
841 832
@@ -961,13 +952,10 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
961 int video_index = plvds_setting_info->lcd_panel_size; 952 int video_index = plvds_setting_info->lcd_panel_size;
962 int set_iga = plvds_setting_info->iga_path; 953 int set_iga = plvds_setting_info->iga_path;
963 int mode_bpp = plvds_setting_info->bpp; 954 int mode_bpp = plvds_setting_info->bpp;
964 int viafb_load_reg_num = 0;
965 int reg_value = 0;
966 int set_hres, set_vres; 955 int set_hres, set_vres;
967 int panel_hres, panel_vres; 956 int panel_hres, panel_vres;
968 u32 pll_D_N; 957 u32 pll_D_N;
969 int offset; 958 int offset;
970 struct io_register *reg = NULL;
971 struct display_timing mode_crt_reg, panel_crt_reg; 959 struct display_timing mode_crt_reg, panel_crt_reg;
972 struct crt_mode_table *panel_crt_table = NULL; 960 struct crt_mode_table *panel_crt_table = NULL;
973 struct VideoModeTable *vmode_tbl = NULL; 961 struct VideoModeTable *vmode_tbl = NULL;
@@ -1047,16 +1035,11 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
1047 } 1035 }
1048 1036
1049 /* Offset for simultaneous */ 1037 /* Offset for simultaneous */
1050 reg_value = offset; 1038 viafb_set_secondary_pitch(offset << 3);
1051 viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
1052 reg = offset_reg.iga2_offset_reg.reg;
1053 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1054 DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n"); 1039 DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
1055 viafb_load_fetch_count_reg(set_hres, 4, IGA2); 1040 viafb_load_fetch_count_reg(set_hres, 4, IGA2);
1056 /* Fetch count for simultaneous */ 1041 /* Fetch count for simultaneous */
1057 } else { /* SAMM */ 1042 } else { /* SAMM */
1058 /* Offset for IGA2 only */
1059 viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga);
1060 /* Fetch count for IGA2 only */ 1043 /* Fetch count for IGA2 only */
1061 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); 1044 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
1062 1045
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 2e1254da9c8c..7cd03e2a1275 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -167,6 +167,10 @@
167#define SR4B 0x4B 167#define SR4B 0x4B
168#define SR4C 0x4C 168#define SR4C 0x4C
169#define SR52 0x52 169#define SR52 0x52
170#define SR57 0x57
171#define SR58 0x58
172#define SR59 0x59
173#define SR5D 0x5D
170#define SR5E 0x5E 174#define SR5E 0x5E
171#define SR65 0x65 175#define SR65 0x65
172 176
@@ -966,6 +970,100 @@
966#define CX700_297_500M 0x00CE0403 970#define CX700_297_500M 0x00CE0403
967#define CX700_122_614M 0x00870802 971#define CX700_122_614M 0x00870802
968 972
973/* PLL for VX855 */
974#define VX855_22_000M 0x007B1005
975#define VX855_25_175M 0x008D1005
976#define VX855_26_719M 0x00961005
977#define VX855_26_880M 0x00961005
978#define VX855_27_000M 0x00971005
979#define VX855_29_581M 0x00A51005
980#define VX855_29_829M 0x00641003
981#define VX855_31_490M 0x00B01005
982#define VX855_31_500M 0x00B01005
983#define VX855_31_728M 0x008E1004
984#define VX855_32_668M 0x00921004
985#define VX855_36_000M 0x00A11004
986#define VX855_40_000M 0x00700C05
987#define VX855_41_291M 0x00730C05
988#define VX855_43_163M 0x00790C05
989#define VX855_45_250M 0x007F0C05 /* 45.46MHz */
990#define VX855_46_000M 0x00670C04
991#define VX855_46_996M 0x00690C04
992#define VX855_48_000M 0x00860C05
993#define VX855_48_875M 0x00890C05
994#define VX855_49_500M 0x00530C03
995#define VX855_52_406M 0x00580C03
996#define VX855_52_977M 0x00940C05
997#define VX855_56_250M 0x009D0C05
998#define VX855_60_466M 0x00A90C05
999#define VX855_61_500M 0x00AC0C05
1000#define VX855_65_000M 0x006D0C03
1001#define VX855_65_178M 0x00B60C05
1002#define VX855_66_750M 0x00700C03 /*67.116MHz */
1003#define VX855_67_295M 0x00BC0C05
1004#define VX855_68_179M 0x00BF0C05
1005#define VX855_68_369M 0x00BF0C05
1006#define VX855_69_924M 0x00C30C05
1007#define VX855_70_159M 0x00C30C05
1008#define VX855_72_000M 0x00A10C04
1009#define VX855_73_023M 0x00CC0C05
1010#define VX855_74_481M 0x00D10C05
1011#define VX855_78_750M 0x006E0805
1012#define VX855_79_466M 0x006F0805
1013#define VX855_80_136M 0x00700805
1014#define VX855_81_627M 0x00720805
1015#define VX855_83_375M 0x00750805
1016#define VX855_83_527M 0x00750805
1017#define VX855_83_950M 0x00750805
1018#define VX855_84_537M 0x00760805
1019#define VX855_84_750M 0x00760805 /* 84.537Mhz */
1020#define VX855_85_500M 0x00760805 /* 85.909080 MHz*/
1021#define VX855_85_860M 0x00760805
1022#define VX855_85_909M 0x00760805
1023#define VX855_88_750M 0x007C0805
1024#define VX855_89_489M 0x007D0805
1025#define VX855_94_500M 0x00840805
1026#define VX855_96_648M 0x00870805
1027#define VX855_97_750M 0x00890805
1028#define VX855_101_000M 0x008D0805
1029#define VX855_106_500M 0x00950805
1030#define VX855_108_000M 0x00970805
1031#define VX855_110_125M 0x00990805
1032#define VX855_112_000M 0x009D0805
1033#define VX855_113_309M 0x009F0805
1034#define VX855_115_000M 0x00A10805
1035#define VX855_118_840M 0x00A60805
1036#define VX855_119_000M 0x00A70805
1037#define VX855_121_750M 0x00AA0805 /* 121.704MHz */
1038#define VX855_122_614M 0x00AC0805
1039#define VX855_126_266M 0x00B10805
1040#define VX855_130_250M 0x00B60805 /* 130.250 */
1041#define VX855_135_000M 0x00BD0805
1042#define VX855_136_700M 0x00BF0805
1043#define VX855_137_750M 0x00C10805
1044#define VX855_138_400M 0x00C20805
1045#define VX855_144_300M 0x00CA0805
1046#define VX855_146_760M 0x00CE0805
1047#define VX855_148_500M 0x00D00805
1048#define VX855_153_920M 0x00540402
1049#define VX855_156_000M 0x006C0405
1050#define VX855_156_867M 0x006E0405
1051#define VX855_157_500M 0x006E0405
1052#define VX855_162_000M 0x00710405
1053#define VX855_172_798M 0x00790405
1054#define VX855_187_000M 0x00830405
1055#define VX855_193_295M 0x00870405
1056#define VX855_202_500M 0x008E0405
1057#define VX855_204_000M 0x008F0405
1058#define VX855_218_500M 0x00990405
1059#define VX855_229_500M 0x00A10405
1060#define VX855_234_000M 0x00A40405
1061#define VX855_267_250M 0x00BB0405
1062#define VX855_297_500M 0x00D00405
1063#define VX855_339_500M 0x00770005
1064#define VX855_340_772M 0x00770005
1065
1066
969/* Definition CRTC Timing Index */ 1067/* Definition CRTC Timing Index */
970#define H_TOTAL_INDEX 0 1068#define H_TOTAL_INDEX 0
971#define H_ADDR_INDEX 1 1069#define H_ADDR_INDEX 1
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 0f3ed4eb236d..15543e968248 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -97,7 +97,7 @@ int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
97 mm1[0] = index; 97 mm1[0] = index;
98 msgs[0].len = 1; msgs[1].len = 1; 98 msgs[0].len = 1; msgs[1].len = 1;
99 msgs[0].buf = mm1; msgs[1].buf = pdata; 99 msgs[0].buf = mm1; msgs[1].buf = pdata;
100 i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2); 100 i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2);
101 101
102 return 0; 102 return 0;
103} 103}
@@ -111,7 +111,7 @@ int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data)
111 msgs.addr = slave_addr / 2; 111 msgs.addr = slave_addr / 2;
112 msgs.len = 2; 112 msgs.len = 2;
113 msgs.buf = msg; 113 msgs.buf = msg;
114 return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1); 114 return i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, &msgs, 1);
115} 115}
116 116
117int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) 117int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
@@ -125,53 +125,53 @@ int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
125 mm1[0] = index; 125 mm1[0] = index;
126 msgs[0].len = 1; msgs[1].len = buff_len; 126 msgs[0].len = 1; msgs[1].len = buff_len;
127 msgs[0].buf = mm1; msgs[1].buf = buff; 127 msgs[0].buf = mm1; msgs[1].buf = buff;
128 i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2); 128 i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2);
129 return 0; 129 return 0;
130} 130}
131 131
132int viafb_create_i2c_bus(void *viapar) 132int viafb_create_i2c_bus(void *viapar)
133{ 133{
134 int ret; 134 int ret;
135 struct viafb_par *par = (struct viafb_par *)viapar; 135 struct via_i2c_stuff *i2c_stuff =
136 136 &((struct viafb_par *)viapar)->shared->i2c_stuff;
137 strcpy(par->i2c_stuff.adapter.name, "via_i2c"); 137
138 par->i2c_stuff.i2c_port = 0x0; 138 strcpy(i2c_stuff->adapter.name, "via_i2c");
139 par->i2c_stuff.adapter.owner = THIS_MODULE; 139 i2c_stuff->i2c_port = 0x0;
140 par->i2c_stuff.adapter.id = 0x01FFFF; 140 i2c_stuff->adapter.owner = THIS_MODULE;
141 par->i2c_stuff.adapter.class = 0; 141 i2c_stuff->adapter.id = 0x01FFFF;
142 par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo; 142 i2c_stuff->adapter.class = 0;
143 par->i2c_stuff.adapter.dev.parent = NULL; 143 i2c_stuff->adapter.algo_data = &i2c_stuff->algo;
144 par->i2c_stuff.algo.setsda = via_i2c_setsda; 144 i2c_stuff->adapter.dev.parent = NULL;
145 par->i2c_stuff.algo.setscl = via_i2c_setscl; 145 i2c_stuff->algo.setsda = via_i2c_setsda;
146 par->i2c_stuff.algo.getsda = via_i2c_getsda; 146 i2c_stuff->algo.setscl = via_i2c_setscl;
147 par->i2c_stuff.algo.getscl = via_i2c_getscl; 147 i2c_stuff->algo.getsda = via_i2c_getsda;
148 par->i2c_stuff.algo.udelay = 40; 148 i2c_stuff->algo.getscl = via_i2c_getscl;
149 par->i2c_stuff.algo.timeout = 20; 149 i2c_stuff->algo.udelay = 40;
150 par->i2c_stuff.algo.data = &par->i2c_stuff; 150 i2c_stuff->algo.timeout = 20;
151 151 i2c_stuff->algo.data = i2c_stuff;
152 i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff); 152
153 i2c_set_adapdata(&i2c_stuff->adapter, i2c_stuff);
153 154
154 /* Raise SCL and SDA */ 155 /* Raise SCL and SDA */
155 par->i2c_stuff.i2c_port = I2CPORTINDEX; 156 i2c_stuff->i2c_port = I2CPORTINDEX;
156 via_i2c_setsda(&par->i2c_stuff, 1); 157 via_i2c_setsda(i2c_stuff, 1);
157 via_i2c_setscl(&par->i2c_stuff, 1); 158 via_i2c_setscl(i2c_stuff, 1);
158 159
159 par->i2c_stuff.i2c_port = GPIOPORTINDEX; 160 i2c_stuff->i2c_port = GPIOPORTINDEX;
160 via_i2c_setsda(&par->i2c_stuff, 1); 161 via_i2c_setsda(i2c_stuff, 1);
161 via_i2c_setscl(&par->i2c_stuff, 1); 162 via_i2c_setscl(i2c_stuff, 1);
162 udelay(20); 163 udelay(20);
163 164
164 ret = i2c_bit_add_bus(&par->i2c_stuff.adapter); 165 ret = i2c_bit_add_bus(&i2c_stuff->adapter);
165 if (ret == 0) 166 if (ret == 0)
166 DEBUG_MSG("I2C bus %s registered.\n", 167 DEBUG_MSG("I2C bus %s registered.\n", i2c_stuff->adapter.name);
167 par->i2c_stuff.adapter.name);
168 else 168 else
169 DEBUG_MSG("Failed to register I2C bus %s.\n", 169 DEBUG_MSG("Failed to register I2C bus %s.\n",
170 par->i2c_stuff.adapter.name); 170 i2c_stuff->adapter.name);
171 return ret; 171 return ret;
172} 172}
173 173
174void viafb_delete_i2c_buss(void *par) 174void viafb_delete_i2c_buss(void *par)
175{ 175{
176 i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter); 176 i2c_del_adapter(&((struct viafb_par *)par)->shared->i2c_stuff.adapter);
177} 177}
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index a0fec298216e..56ec696e8afa 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -20,11 +20,12 @@
20 */ 20 */
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/seq_file.h>
24#include <linux/stat.h>
23#define _MASTER_FILE 25#define _MASTER_FILE
24 26
25#include "global.h" 27#include "global.h"
26 28
27static int MAX_CURS = 32;
28static struct fb_var_screeninfo default_var; 29static struct fb_var_screeninfo default_var;
29static char *viafb_name = "Via"; 30static char *viafb_name = "Via";
30static u32 pseudo_pal[17]; 31static u32 pseudo_pal[17];
@@ -32,14 +33,12 @@ static u32 pseudo_pal[17];
32/* video mode */ 33/* video mode */
33static char *viafb_mode = "640x480"; 34static char *viafb_mode = "640x480";
34static char *viafb_mode1 = "640x480"; 35static char *viafb_mode1 = "640x480";
35static int viafb_resMode = VIA_RES_640X480; 36
37static int viafb_accel = 1;
36 38
37/* Added for specifying active devices.*/ 39/* Added for specifying active devices.*/
38char *viafb_active_dev = ""; 40char *viafb_active_dev = "";
39 41
40/* Added for specifying video on devices.*/
41char *viafb_video_dev = "";
42
43/*Added for specify lcd output port*/ 42/*Added for specify lcd output port*/
44char *viafb_lcd_port = ""; 43char *viafb_lcd_port = "";
45char *viafb_dvi_port = ""; 44char *viafb_dvi_port = "";
@@ -51,71 +50,20 @@ static void apply_second_mode_setting(struct fb_var_screeninfo
51 *sec_var); 50 *sec_var);
52static void retrieve_device_setting(struct viafb_ioctl_setting 51static void retrieve_device_setting(struct viafb_ioctl_setting
53 *setting_info); 52 *setting_info);
54static void viafb_set_video_device(u32 video_dev_info);
55static void viafb_get_video_device(u32 *video_dev_info);
56
57/* Mode information */
58static const struct viafb_modeinfo viafb_modentry[] = {
59 {480, 640, VIA_RES_480X640, "480x640"},
60 {640, 480, VIA_RES_640X480, "640x480"},
61 {800, 480, VIA_RES_800X480, "800x480"},
62 {800, 600, VIA_RES_800X600, "800x600"},
63 {1024, 768, VIA_RES_1024X768, "1024x768"},
64 {1152, 864, VIA_RES_1152X864, "1152x864"},
65 {1280, 1024, VIA_RES_1280X1024, "1280x1024"},
66 {1600, 1200, VIA_RES_1600X1200, "1600x1200"},
67 {1440, 1050, VIA_RES_1440X1050, "1440x1050"},
68 {1280, 768, VIA_RES_1280X768, "1280x768"},
69 {1280, 800, VIA_RES_1280X800, "1280x800"},
70 {1280, 960, VIA_RES_1280X960, "1280x960"},
71 {1920, 1440, VIA_RES_1920X1440, "1920x1440"},
72 {848, 480, VIA_RES_848X480, "848x480"},
73 {1400, 1050, VIA_RES_1400X1050, "1400x1050"},
74 {720, 480, VIA_RES_720X480, "720x480"},
75 {720, 576, VIA_RES_720X576, "720x576"},
76 {1024, 512, VIA_RES_1024X512, "1024x512"},
77 {1024, 576, VIA_RES_1024X576, "1024x576"},
78 {1024, 600, VIA_RES_1024X600, "1024x600"},
79 {1280, 720, VIA_RES_1280X720, "1280x720"},
80 {1920, 1080, VIA_RES_1920X1080, "1920x1080"},
81 {1366, 768, VIA_RES_1368X768, "1368x768"},
82 {1680, 1050, VIA_RES_1680X1050, "1680x1050"},
83 {960, 600, VIA_RES_960X600, "960x600"},
84 {1000, 600, VIA_RES_1000X600, "1000x600"},
85 {1024, 576, VIA_RES_1024X576, "1024x576"},
86 {1024, 600, VIA_RES_1024X600, "1024x600"},
87 {1088, 612, VIA_RES_1088X612, "1088x612"},
88 {1152, 720, VIA_RES_1152X720, "1152x720"},
89 {1200, 720, VIA_RES_1200X720, "1200x720"},
90 {1280, 600, VIA_RES_1280X600, "1280x600"},
91 {1360, 768, VIA_RES_1360X768, "1360x768"},
92 {1440, 900, VIA_RES_1440X900, "1440x900"},
93 {1600, 900, VIA_RES_1600X900, "1600x900"},
94 {1600, 1024, VIA_RES_1600X1024, "1600x1024"},
95 {1792, 1344, VIA_RES_1792X1344, "1792x1344"},
96 {1856, 1392, VIA_RES_1856X1392, "1856x1392"},
97 {1920, 1200, VIA_RES_1920X1200, "1920x1200"},
98 {2048, 1536, VIA_RES_2048X1536, "2048x1536"},
99 {0, 0, VIA_RES_INVALID, "640x480"}
100};
101 53
102static struct fb_ops viafb_ops; 54static struct fb_ops viafb_ops;
103 55
104static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
105{
106 struct viafb_par *ppar;
107 ppar = info->par;
108
109 DEBUG_MSG(KERN_INFO "viafb_update_fix!\n");
110 56
111 fix->visual = 57static void viafb_update_fix(struct fb_info *info)
112 ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 58{
113 fix->line_length = ppar->linelength; 59 u32 bpp = info->var.bits_per_pixel;
114 60
115 return 0; 61 info->fix.visual =
62 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
63 info->fix.line_length =
64 ((info->var.xres_virtual + 7) & ~7) * bpp / 8;
116} 65}
117 66
118
119static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, 67static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
120 struct viafb_par *viaparinfo) 68 struct viafb_par *viaparinfo)
121{ 69{
@@ -124,8 +72,6 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
124 72
125 fix->smem_start = viaparinfo->fbmem; 73 fix->smem_start = viaparinfo->fbmem;
126 fix->smem_len = viaparinfo->fbmem_free; 74 fix->smem_len = viaparinfo->fbmem_free;
127 fix->mmio_start = viaparinfo->mmio_base;
128 fix->mmio_len = viaparinfo->mmio_len;
129 75
130 fix->type = FB_TYPE_PACKED_PIXELS; 76 fix->type = FB_TYPE_PACKED_PIXELS;
131 fix->type_aux = 0; 77 fix->type_aux = 0;
@@ -148,28 +94,12 @@ static int viafb_release(struct fb_info *info, int user)
148 return 0; 94 return 0;
149} 95}
150 96
151static void viafb_update_viafb_par(struct fb_info *info)
152{
153 struct viafb_par *ppar;
154
155 ppar = info->par;
156 ppar->bpp = info->var.bits_per_pixel;
157 ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8;
158 ppar->hres = info->var.xres;
159 ppar->vres = info->var.yres;
160 ppar->xoffset = info->var.xoffset;
161 ppar->yoffset = info->var.yoffset;
162}
163
164static int viafb_check_var(struct fb_var_screeninfo *var, 97static int viafb_check_var(struct fb_var_screeninfo *var,
165 struct fb_info *info) 98 struct fb_info *info)
166{ 99{
167 int vmode_index, htotal, vtotal; 100 int vmode_index, htotal, vtotal;
168 struct viafb_par *ppar; 101 struct viafb_par *ppar = info->par;
169 u32 long_refresh; 102 u32 long_refresh;
170 struct viafb_par *p_viafb_par;
171 ppar = info->par;
172
173 103
174 DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); 104 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
175 /* Sanity check */ 105 /* Sanity check */
@@ -177,7 +107,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
177 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) 107 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
178 return -EINVAL; 108 return -EINVAL;
179 109
180 vmode_index = viafb_get_mode_index(var->xres, var->yres, 0); 110 vmode_index = viafb_get_mode_index(var->xres, var->yres);
181 if (vmode_index == VIA_RES_INVALID) { 111 if (vmode_index == VIA_RES_INVALID) {
182 DEBUG_MSG(KERN_INFO 112 DEBUG_MSG(KERN_INFO
183 "viafb: Mode %dx%dx%d not supported!!\n", 113 "viafb: Mode %dx%dx%d not supported!!\n",
@@ -213,34 +143,32 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
213 143
214 /* Adjust var according to our driver's own table */ 144 /* Adjust var according to our driver's own table */
215 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); 145 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
216 146 if (info->var.accel_flags & FB_ACCELF_TEXT &&
217 /* This is indeed a patch for VT3353 */ 147 !ppar->shared->engine_mmio)
218 if (!info->par) 148 info->var.accel_flags = 0;
219 return -1;
220 p_viafb_par = (struct viafb_par *)info->par;
221 if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800)
222 var->accel_flags = 0;
223 149
224 return 0; 150 return 0;
225} 151}
226 152
227static int viafb_set_par(struct fb_info *info) 153static int viafb_set_par(struct fb_info *info)
228{ 154{
155 struct viafb_par *viapar = info->par;
229 int vmode_index; 156 int vmode_index;
230 int vmode_index1 = 0; 157 int vmode_index1 = 0;
231 DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); 158 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
232 159
160 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
233 viafb_update_device_setting(info->var.xres, info->var.yres, 161 viafb_update_device_setting(info->var.xres, info->var.yres,
234 info->var.bits_per_pixel, viafb_refresh, 0); 162 info->var.bits_per_pixel, viafb_refresh, 0);
235 163
236 vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0); 164 vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres);
237 165
238 if (viafb_SAMM_ON == 1) { 166 if (viafb_SAMM_ON == 1) {
239 DEBUG_MSG(KERN_INFO 167 DEBUG_MSG(KERN_INFO
240 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", 168 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
241 viafb_second_xres, viafb_second_yres, viafb_bpp1); 169 viafb_second_xres, viafb_second_yres, viafb_bpp1);
242 vmode_index1 = viafb_get_mode_index(viafb_second_xres, 170 vmode_index1 = viafb_get_mode_index(viafb_second_xres,
243 viafb_second_yres, 1); 171 viafb_second_yres);
244 DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n", 172 DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
245 vmode_index1); 173 vmode_index1);
246 174
@@ -253,21 +181,12 @@ static int viafb_set_par(struct fb_info *info)
253 info->var.bits_per_pixel, vmode_index1, 181 info->var.bits_per_pixel, vmode_index1,
254 viafb_second_xres, viafb_second_yres, viafb_bpp1); 182 viafb_second_xres, viafb_second_yres, viafb_bpp1);
255 183
256 /*We should set memory offset according virtual_x */ 184 viafb_update_fix(info);
257 /*Fix me:put this function into viafb_setmode */
258 viafb_memory_pitch_patch(info);
259
260 /* Update ***fb_par information */
261 viafb_update_viafb_par(info);
262
263 /* Update other fixed information */
264 viafb_update_fix(&info->fix, info);
265 viafb_bpp = info->var.bits_per_pixel; 185 viafb_bpp = info->var.bits_per_pixel;
266 /* Update viafb_accel, it is necessary to our 2D accelerate */ 186 if (info->var.accel_flags & FB_ACCELF_TEXT)
267 viafb_accel = info->var.accel_flags; 187 info->flags &= ~FBINFO_HWACCEL_DISABLED;
268 188 else
269 if (viafb_accel) 189 info->flags |= FBINFO_HWACCEL_DISABLED;
270 viafb_set_2d_color_depth(info->var.bits_per_pixel);
271 } 190 }
272 191
273 return 0; 192 return 0;
@@ -504,12 +423,7 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
504 var->bits_per_pixel / 16; 423 var->bits_per_pixel / 16;
505 424
506 DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset); 425 DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
507 426 viafb_set_primary_address(offset);
508 viafb_write_reg_mask(0x48, 0x3d4, ((offset >> 24) & 0x3), 0x3);
509 viafb_write_reg_mask(0x34, 0x3d4, ((offset >> 16) & 0xff), 0xff);
510 viafb_write_reg_mask(0x0c, 0x3d4, ((offset >> 8) & 0xff), 0xff);
511 viafb_write_reg_mask(0x0d, 0x3d4, (offset & 0xff), 0xff);
512
513 return 0; 427 return 0;
514} 428}
515 429
@@ -561,7 +475,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
561 475
562 u32 __user *argp = (u32 __user *) arg; 476 u32 __user *argp = (u32 __user *) arg;
563 u32 gpu32; 477 u32 gpu32;
564 u32 video_dev_info = 0;
565 478
566 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); 479 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
567 memset(&u, 0, sizeof(u)); 480 memset(&u, 0, sizeof(u));
@@ -793,15 +706,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
793 if (put_user(state_info, argp)) 706 if (put_user(state_info, argp))
794 return -EFAULT; 707 return -EFAULT;
795 break; 708 break;
796 case VIAFB_SET_VIDEO_DEVICE:
797 get_user(video_dev_info, argp);
798 viafb_set_video_device(video_dev_info);
799 break;
800 case VIAFB_GET_VIDEO_DEVICE:
801 viafb_get_video_device(&video_dev_info);
802 if (put_user(video_dev_info, argp))
803 return -EFAULT;
804 break;
805 case VIAFB_SYNC_SURFACE: 709 case VIAFB_SYNC_SURFACE:
806 DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n"); 710 DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
807 break; 711 break;
@@ -867,10 +771,12 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
867static void viafb_fillrect(struct fb_info *info, 771static void viafb_fillrect(struct fb_info *info,
868 const struct fb_fillrect *rect) 772 const struct fb_fillrect *rect)
869{ 773{
870 u32 col = 0, rop = 0; 774 struct viafb_par *viapar = info->par;
871 int pitch; 775 struct viafb_shared *shared = viapar->shared;
776 u32 fg_color;
777 u8 rop;
872 778
873 if (!viafb_accel) { 779 if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
874 cfb_fillrect(info, rect); 780 cfb_fillrect(info, rect);
875 return; 781 return;
876 } 782 }
@@ -878,68 +784,31 @@ static void viafb_fillrect(struct fb_info *info,
878 if (!rect->width || !rect->height) 784 if (!rect->width || !rect->height)
879 return; 785 return;
880 786
881 switch (rect->rop) { 787 if (info->fix.visual == FB_VISUAL_TRUECOLOR)
882 case ROP_XOR: 788 fg_color = ((u32 *)info->pseudo_palette)[rect->color];
789 else
790 fg_color = rect->color;
791
792 if (rect->rop == ROP_XOR)
883 rop = 0x5A; 793 rop = 0x5A;
884 break; 794 else
885 case ROP_COPY:
886 default:
887 rop = 0xF0; 795 rop = 0xF0;
888 break;
889 }
890
891 switch (info->var.bits_per_pixel) {
892 case 8:
893 col = rect->color;
894 break;
895 case 16:
896 col = ((u32 *) (info->pseudo_palette))[rect->color];
897 break;
898 case 32:
899 col = ((u32 *) (info->pseudo_palette))[rect->color];
900 break;
901 }
902
903 /* BitBlt Source Address */
904 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
905 /* Source Base Address */
906 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
907 /* Destination Base Address */
908 writel(((unsigned long) (info->screen_base) -
909 (unsigned long) viafb_FB_MM) >> 3,
910 viaparinfo->io_virt + VIA_REG_DSTBASE);
911 /* Pitch */
912 pitch = (info->var.xres_virtual + 7) & ~7;
913 writel(VIA_PITCH_ENABLE |
914 (((pitch *
915 info->var.bits_per_pixel >> 3) >> 3) |
916 (((pitch * info->
917 var.bits_per_pixel >> 3) >> 3) << 16)),
918 viaparinfo->io_virt + VIA_REG_PITCH);
919 /* BitBlt Destination Address */
920 writel(((rect->dy << 16) | rect->dx),
921 viaparinfo->io_virt + VIA_REG_DSTPOS);
922 /* Dimension: width & height */
923 writel((((rect->height - 1) << 16) | (rect->width - 1)),
924 viaparinfo->io_virt + VIA_REG_DIMENSION);
925 /* Forground color or Destination color */
926 writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
927 /* GE Command */
928 writel((0x01 | 0x2000 | (rop << 24)),
929 viaparinfo->io_virt + VIA_REG_GECMD);
930 796
797 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
798 if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_FILL,
799 rect->width, rect->height, info->var.bits_per_pixel,
800 viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
801 NULL, 0, 0, 0, 0, fg_color, 0, rop))
802 cfb_fillrect(info, rect);
931} 803}
932 804
933static void viafb_copyarea(struct fb_info *info, 805static void viafb_copyarea(struct fb_info *info,
934 const struct fb_copyarea *area) 806 const struct fb_copyarea *area)
935{ 807{
936 u32 dy = area->dy, sy = area->sy, direction = 0x0; 808 struct viafb_par *viapar = info->par;
937 u32 sx = area->sx, dx = area->dx, width = area->width; 809 struct viafb_shared *shared = viapar->shared;
938 int pitch;
939
940 DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n");
941 810
942 if (!viafb_accel) { 811 if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
943 cfb_copyarea(info, area); 812 cfb_copyarea(info, area);
944 return; 813 return;
945 } 814 }
@@ -947,263 +816,148 @@ static void viafb_copyarea(struct fb_info *info,
947 if (!area->width || !area->height) 816 if (!area->width || !area->height)
948 return; 817 return;
949 818
950 if (sy < dy) { 819 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
951 dy += area->height - 1; 820 if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_COLOR,
952 sy += area->height - 1; 821 area->width, area->height, info->var.bits_per_pixel,
953 direction |= 0x4000; 822 viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
954 } 823 NULL, viapar->vram_addr, info->fix.line_length,
955 824 area->sx, area->sy, 0, 0, 0))
956 if (sx < dx) { 825 cfb_copyarea(info, area);
957 dx += width - 1;
958 sx += width - 1;
959 direction |= 0x8000;
960 }
961
962 /* Source Base Address */
963 writel(((unsigned long) (info->screen_base) -
964 (unsigned long) viafb_FB_MM) >> 3,
965 viaparinfo->io_virt + VIA_REG_SRCBASE);
966 /* Destination Base Address */
967 writel(((unsigned long) (info->screen_base) -
968 (unsigned long) viafb_FB_MM) >> 3,
969 viaparinfo->io_virt + VIA_REG_DSTBASE);
970 /* Pitch */
971 pitch = (info->var.xres_virtual + 7) & ~7;
972 /* VIA_PITCH_ENABLE can be omitted now. */
973 writel(VIA_PITCH_ENABLE |
974 (((pitch *
975 info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
976 info->var.
977 bits_per_pixel
978 >> 3) >> 3)
979 << 16)),
980 viaparinfo->io_virt + VIA_REG_PITCH);
981 /* BitBlt Source Address */
982 writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS);
983 /* BitBlt Destination Address */
984 writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS);
985 /* Dimension: width & height */
986 writel((((area->height - 1) << 16) | (area->width - 1)),
987 viaparinfo->io_virt + VIA_REG_DIMENSION);
988 /* GE Command */
989 writel((0x01 | direction | (0xCC << 24)),
990 viaparinfo->io_virt + VIA_REG_GECMD);
991
992} 826}
993 827
994static void viafb_imageblit(struct fb_info *info, 828static void viafb_imageblit(struct fb_info *info,
995 const struct fb_image *image) 829 const struct fb_image *image)
996{ 830{
997 u32 size, bg_col = 0, fg_col = 0, *udata; 831 struct viafb_par *viapar = info->par;
998 int i; 832 struct viafb_shared *shared = viapar->shared;
999 int pitch; 833 u32 fg_color = 0, bg_color = 0;
834 u8 op;
1000 835
1001 if (!viafb_accel) { 836 if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt ||
837 (image->depth != 1 && image->depth != viapar->depth)) {
1002 cfb_imageblit(info, image); 838 cfb_imageblit(info, image);
1003 return; 839 return;
1004 } 840 }
1005 841
1006 udata = (u32 *) image->data; 842 if (image->depth == 1) {
1007 843 op = VIA_BITBLT_MONO;
1008 switch (info->var.bits_per_pixel) { 844 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
1009 case 8: 845 fg_color =
1010 bg_col = image->bg_color; 846 ((u32 *)info->pseudo_palette)[image->fg_color];
1011 fg_col = image->fg_color; 847 bg_color =
1012 break; 848 ((u32 *)info->pseudo_palette)[image->bg_color];
1013 case 16: 849 } else {
1014 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; 850 fg_color = image->fg_color;
1015 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color]; 851 bg_color = image->bg_color;
1016 break; 852 }
1017 case 32: 853 } else
1018 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color]; 854 op = VIA_BITBLT_COLOR;
1019 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
1020 break;
1021 }
1022 size = image->width * image->height;
1023
1024 /* Source Base Address */
1025 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
1026 /* Destination Base Address */
1027 writel(((unsigned long) (info->screen_base) -
1028 (unsigned long) viafb_FB_MM) >> 3,
1029 viaparinfo->io_virt + VIA_REG_DSTBASE);
1030 /* Pitch */
1031 pitch = (info->var.xres_virtual + 7) & ~7;
1032 writel(VIA_PITCH_ENABLE |
1033 (((pitch *
1034 info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
1035 info->var.
1036 bits_per_pixel
1037 >> 3) >> 3)
1038 << 16)),
1039 viaparinfo->io_virt + VIA_REG_PITCH);
1040 /* BitBlt Source Address */
1041 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
1042 /* BitBlt Destination Address */
1043 writel(((image->dy << 16) | image->dx),
1044 viaparinfo->io_virt + VIA_REG_DSTPOS);
1045 /* Dimension: width & height */
1046 writel((((image->height - 1) << 16) | (image->width - 1)),
1047 viaparinfo->io_virt + VIA_REG_DIMENSION);
1048 /* fb color */
1049 writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
1050 /* bg color */
1051 writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR);
1052 /* GE Command */
1053 writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD);
1054
1055 for (i = 0; i < size / 4; i++) {
1056 writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE);
1057 udata++;
1058 }
1059 855
856 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
857 if (shared->hw_bitblt(shared->engine_mmio, op,
858 image->width, image->height, info->var.bits_per_pixel,
859 viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
860 (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
861 cfb_imageblit(info, image);
1060} 862}
1061 863
1062static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) 864static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1063{ 865{
1064 u32 temp, xx, yy, bg_col = 0, fg_col = 0; 866 struct viafb_par *viapar = info->par;
1065 int i, j = 0; 867 void __iomem *engine = viapar->shared->engine_mmio;
1066 static int hw_cursor; 868 u32 temp, xx, yy, bg_color = 0, fg_color = 0,
1067 struct viafb_par *p_viafb_par; 869 chip_name = viapar->shared->chip_info.gfx_chip_name;
1068 870 int i, j = 0, cur_size = 64;
1069 if (viafb_accel)
1070 hw_cursor = 1;
1071
1072 if (!viafb_accel) {
1073 if (hw_cursor) {
1074 viafb_show_hw_cursor(info, HW_Cursor_OFF);
1075 hw_cursor = 0;
1076 }
1077 return -ENODEV;
1078 }
1079 871
1080 if ((((struct viafb_par *)(info->par))->iga_path == IGA2) 872 if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
1081 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
1082 return -ENODEV; 873 return -ENODEV;
1083 874
1084 /* When duoview and using lcd , use soft cursor */ 875 if (chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2)
1085 if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview)
1086 return -ENODEV; 876 return -ENODEV;
1087 877
1088 viafb_show_hw_cursor(info, HW_Cursor_OFF); 878 viafb_show_hw_cursor(info, HW_Cursor_OFF);
1089 viacursor = *cursor;
1090 879
1091 if (cursor->set & FB_CUR_SETHOT) { 880 if (cursor->set & FB_CUR_SETHOT) {
1092 viacursor.hot = cursor->hot; 881 temp = (cursor->hot.x << 16) + cursor->hot.y;
1093 temp = ((viacursor.hot.x) << 16) + viacursor.hot.y; 882 writel(temp, engine + VIA_REG_CURSOR_ORG);
1094 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
1095 } 883 }
1096 884
1097 if (cursor->set & FB_CUR_SETPOS) { 885 if (cursor->set & FB_CUR_SETPOS) {
1098 viacursor.image.dx = cursor->image.dx;
1099 viacursor.image.dy = cursor->image.dy;
1100 yy = cursor->image.dy - info->var.yoffset; 886 yy = cursor->image.dy - info->var.yoffset;
1101 xx = cursor->image.dx - info->var.xoffset; 887 xx = cursor->image.dx - info->var.xoffset;
1102 temp = yy & 0xFFFF; 888 temp = yy & 0xFFFF;
1103 temp |= (xx << 16); 889 temp |= (xx << 16);
1104 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS); 890 writel(temp, engine + VIA_REG_CURSOR_POS);
1105 } 891 }
1106 892
1107 if (cursor->set & FB_CUR_SETSIZE) { 893 if (cursor->image.width <= 32 && cursor->image.height <= 32)
1108 temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE); 894 cur_size = 32;
895 else if (cursor->image.width <= 64 && cursor->image.height <= 64)
896 cur_size = 64;
897 else {
898 printk(KERN_WARNING "viafb_cursor: The cursor is too large "
899 "%dx%d", cursor->image.width, cursor->image.height);
900 return -ENXIO;
901 }
1109 902
1110 if ((cursor->image.width <= 32) 903 if (cursor->set & FB_CUR_SETSIZE) {
1111 && (cursor->image.height <= 32)) { 904 temp = readl(engine + VIA_REG_CURSOR_MODE);
1112 MAX_CURS = 32; 905 if (cur_size == 32)
1113 temp |= 0x2; 906 temp |= 0x2;
1114 } else if ((cursor->image.width <= 64) 907 else
1115 && (cursor->image.height <= 64)) { 908 temp &= ~0x2;
1116 MAX_CURS = 64;
1117 temp &= 0xFFFFFFFD;
1118 } else {
1119 DEBUG_MSG(KERN_INFO
1120 "The cursor image is biger than 64x64 bits...\n");
1121 return -ENXIO;
1122 }
1123 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
1124 909
1125 viacursor.image.height = cursor->image.height; 910 writel(temp, engine + VIA_REG_CURSOR_MODE);
1126 viacursor.image.width = cursor->image.width;
1127 } 911 }
1128 912
1129 if (cursor->set & FB_CUR_SETCMAP) { 913 if (cursor->set & FB_CUR_SETCMAP) {
1130 viacursor.image.fg_color = cursor->image.fg_color; 914 fg_color = cursor->image.fg_color;
1131 viacursor.image.bg_color = cursor->image.bg_color; 915 bg_color = cursor->image.bg_color;
1132 916 if (chip_name == UNICHROME_CX700 ||
1133 switch (info->var.bits_per_pixel) { 917 chip_name == UNICHROME_VX800 ||
1134 case 8: 918 chip_name == UNICHROME_VX855) {
1135 case 16: 919 fg_color =
1136 case 32: 920 ((info->cmap.red[fg_color] & 0xFFC0) << 14) |
1137 bg_col = 921 ((info->cmap.green[fg_color] & 0xFFC0) << 4) |
1138 (0xFF << 24) | 922 ((info->cmap.blue[fg_color] & 0xFFC0) >> 6);
1139 (((info->cmap.red)[viacursor.image.bg_color] & 923 bg_color =
1140 0xFF00) << 8) | 924 ((info->cmap.red[bg_color] & 0xFFC0) << 14) |
1141 ((info->cmap.green)[viacursor.image.bg_color] & 925 ((info->cmap.green[bg_color] & 0xFFC0) << 4) |
1142 0xFF00) | 926 ((info->cmap.blue[bg_color] & 0xFFC0) >> 6);
1143 (((info->cmap.blue)[viacursor.image.bg_color] & 927 } else {
1144 0xFF00) >> 8); 928 fg_color =
1145 fg_col = 929 ((info->cmap.red[fg_color] & 0xFF00) << 8) |
1146 (0xFF << 24) | 930 (info->cmap.green[fg_color] & 0xFF00) |
1147 (((info->cmap.red)[viacursor.image.fg_color] & 931 ((info->cmap.blue[fg_color] & 0xFF00) >> 8);
1148 0xFF00) << 8) | 932 bg_color =
1149 ((info->cmap.green)[viacursor.image.fg_color] & 933 ((info->cmap.red[bg_color] & 0xFF00) << 8) |
1150 0xFF00) | 934 (info->cmap.green[bg_color] & 0xFF00) |
1151 (((info->cmap.blue)[viacursor.image.fg_color] & 935 ((info->cmap.blue[bg_color] & 0xFF00) >> 8);
1152 0xFF00) >> 8);
1153 break;
1154 default:
1155 return 0;
1156 }
1157
1158 /* This is indeed a patch for VT3324/VT3353 */
1159 if (!info->par)
1160 return 0;
1161 p_viafb_par = (struct viafb_par *)info->par;
1162
1163 if ((p_viafb_par->chip_info->gfx_chip_name ==
1164 UNICHROME_CX700) ||
1165 ((p_viafb_par->chip_info->gfx_chip_name ==
1166 UNICHROME_VX800))) {
1167 bg_col =
1168 (((info->cmap.red)[viacursor.image.bg_color] &
1169 0xFFC0) << 14) |
1170 (((info->cmap.green)[viacursor.image.bg_color] &
1171 0xFFC0) << 4) |
1172 (((info->cmap.blue)[viacursor.image.bg_color] &
1173 0xFFC0) >> 6);
1174 fg_col =
1175 (((info->cmap.red)[viacursor.image.fg_color] &
1176 0xFFC0) << 14) |
1177 (((info->cmap.green)[viacursor.image.fg_color] &
1178 0xFFC0) << 4) |
1179 (((info->cmap.blue)[viacursor.image.fg_color] &
1180 0xFFC0) >> 6);
1181 } 936 }
1182 937
1183 writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG); 938 writel(bg_color, engine + VIA_REG_CURSOR_BG);
1184 writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG); 939 writel(fg_color, engine + VIA_REG_CURSOR_FG);
1185 } 940 }
1186 941
1187 if (cursor->set & FB_CUR_SETSHAPE) { 942 if (cursor->set & FB_CUR_SETSHAPE) {
1188 struct { 943 struct {
1189 u8 data[CURSOR_SIZE / 8]; 944 u8 data[CURSOR_SIZE];
1190 u32 bak[CURSOR_SIZE / 32]; 945 u32 bak[CURSOR_SIZE / 4];
1191 } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC); 946 } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
1192 int size = 947 int size = ((cursor->image.width + 7) >> 3) *
1193 ((viacursor.image.width + 7) >> 3) * 948 cursor->image.height;
1194 viacursor.image.height;
1195 949
1196 if (cr_data == NULL) 950 if (!cr_data)
1197 goto out; 951 return -ENOMEM;
1198 952
1199 if (MAX_CURS == 32) { 953 if (cur_size == 32) {
1200 for (i = 0; i < (CURSOR_SIZE / 32); i++) { 954 for (i = 0; i < (CURSOR_SIZE / 4); i++) {
1201 cr_data->bak[i] = 0x0; 955 cr_data->bak[i] = 0x0;
1202 cr_data->bak[i + 1] = 0xFFFFFFFF; 956 cr_data->bak[i + 1] = 0xFFFFFFFF;
1203 i += 1; 957 i += 1;
1204 } 958 }
1205 } else if (MAX_CURS == 64) { 959 } else {
1206 for (i = 0; i < (CURSOR_SIZE / 32); i++) { 960 for (i = 0; i < (CURSOR_SIZE / 4); i++) {
1207 cr_data->bak[i] = 0x0; 961 cr_data->bak[i] = 0x0;
1208 cr_data->bak[i + 1] = 0x0; 962 cr_data->bak[i + 1] = 0x0;
1209 cr_data->bak[i + 2] = 0xFFFFFFFF; 963 cr_data->bak[i + 2] = 0xFFFFFFFF;
@@ -1212,27 +966,27 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1212 } 966 }
1213 } 967 }
1214 968
1215 switch (viacursor.rop) { 969 switch (cursor->rop) {
1216 case ROP_XOR: 970 case ROP_XOR:
1217 for (i = 0; i < size; i++) 971 for (i = 0; i < size; i++)
1218 cr_data->data[i] = viacursor.mask[i]; 972 cr_data->data[i] = cursor->mask[i];
1219 break; 973 break;
1220 case ROP_COPY: 974 case ROP_COPY:
1221 975
1222 for (i = 0; i < size; i++) 976 for (i = 0; i < size; i++)
1223 cr_data->data[i] = viacursor.mask[i]; 977 cr_data->data[i] = cursor->mask[i];
1224 break; 978 break;
1225 default: 979 default:
1226 break; 980 break;
1227 } 981 }
1228 982
1229 if (MAX_CURS == 32) { 983 if (cur_size == 32) {
1230 for (i = 0; i < size; i++) { 984 for (i = 0; i < size; i++) {
1231 cr_data->bak[j] = (u32) cr_data->data[i]; 985 cr_data->bak[j] = (u32) cr_data->data[i];
1232 cr_data->bak[j + 1] = ~cr_data->bak[j]; 986 cr_data->bak[j + 1] = ~cr_data->bak[j];
1233 j += 2; 987 j += 2;
1234 } 988 }
1235 } else if (MAX_CURS == 64) { 989 } else {
1236 for (i = 0; i < size; i++) { 990 for (i = 0; i < size; i++) {
1237 cr_data->bak[j] = (u32) cr_data->data[i]; 991 cr_data->bak[j] = (u32) cr_data->data[i];
1238 cr_data->bak[j + 1] = 0x0; 992 cr_data->bak[j + 1] = 0x0;
@@ -1242,14 +996,12 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1242 } 996 }
1243 } 997 }
1244 998
1245 memcpy(((struct viafb_par *)(info->par))->fbmem_virt + 999 memcpy_toio(viafbinfo->screen_base + viapar->shared->
1246 ((struct viafb_par *)(info->par))->cursor_start, 1000 cursor_vram_addr, cr_data->bak, CURSOR_SIZE);
1247 cr_data->bak, CURSOR_SIZE);
1248out:
1249 kfree(cr_data); 1001 kfree(cr_data);
1250 } 1002 }
1251 1003
1252 if (viacursor.enable) 1004 if (cursor->enable)
1253 viafb_show_hw_cursor(info, HW_Cursor_ON); 1005 viafb_show_hw_cursor(info, HW_Cursor_ON);
1254 1006
1255 return 0; 1007 return 0;
@@ -1257,28 +1009,26 @@ out:
1257 1009
1258static int viafb_sync(struct fb_info *info) 1010static int viafb_sync(struct fb_info *info)
1259{ 1011{
1260 if (viafb_accel) 1012 if (!(info->flags & FBINFO_HWACCEL_DISABLED))
1261 viafb_wait_engine_idle(); 1013 viafb_wait_engine_idle(info);
1262 return 0; 1014 return 0;
1263} 1015}
1264 1016
1265int viafb_get_mode_index(int hres, int vres, int flag) 1017int viafb_get_mode_index(int hres, int vres)
1266{ 1018{
1267 u32 i; 1019 u32 i;
1268 DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); 1020 DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
1269 1021
1270 for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++) 1022 for (i = 0; i < NUM_TOTAL_MODETABLE; i++)
1271 if (viafb_modentry[i].xres == hres && 1023 if (CLE266Modes[i].mode_array &&
1272 viafb_modentry[i].yres == vres) 1024 CLE266Modes[i].crtc[0].crtc.hor_addr == hres &&
1025 CLE266Modes[i].crtc[0].crtc.ver_addr == vres)
1273 break; 1026 break;
1274 1027
1275 viafb_resMode = viafb_modentry[i].mode_index; 1028 if (i == NUM_TOTAL_MODETABLE)
1276 if (flag) 1029 return VIA_RES_INVALID;
1277 viafb_mode1 = viafb_modentry[i].mode_res;
1278 else
1279 viafb_mode = viafb_modentry[i].mode_res;
1280 1030
1281 return viafb_resMode; 1031 return CLE266Modes[i].ModeIndex;
1282} 1032}
1283 1033
1284static void check_available_device_to_enable(int device_id) 1034static void check_available_device_to_enable(int device_id)
@@ -1382,36 +1132,11 @@ static void viafb_set_device(struct device_t active_dev)
1382 viafb_SAMM_ON = active_dev.samm; 1132 viafb_SAMM_ON = active_dev.samm;
1383 viafb_primary_dev = active_dev.primary_dev; 1133 viafb_primary_dev = active_dev.primary_dev;
1384 1134
1385 viafb_set_start_addr(); 1135 viafb_set_primary_address(0);
1136 viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
1386 viafb_set_iga_path(); 1137 viafb_set_iga_path();
1387} 1138}
1388 1139
1389static void viafb_set_video_device(u32 video_dev_info)
1390{
1391 viaparinfo->video_on_crt = STATE_OFF;
1392 viaparinfo->video_on_dvi = STATE_OFF;
1393 viaparinfo->video_on_lcd = STATE_OFF;
1394
1395 /* Check available device to enable: */
1396 if ((video_dev_info & CRT_Device) == CRT_Device)
1397 viaparinfo->video_on_crt = STATE_ON;
1398 else if ((video_dev_info & DVI_Device) == DVI_Device)
1399 viaparinfo->video_on_dvi = STATE_ON;
1400 else if ((video_dev_info & LCD_Device) == LCD_Device)
1401 viaparinfo->video_on_lcd = STATE_ON;
1402}
1403
1404static void viafb_get_video_device(u32 *video_dev_info)
1405{
1406 *video_dev_info = None_Device;
1407 if (viaparinfo->video_on_crt == STATE_ON)
1408 *video_dev_info |= CRT_Device;
1409 else if (viaparinfo->video_on_dvi == STATE_ON)
1410 *video_dev_info |= DVI_Device;
1411 else if (viaparinfo->video_on_lcd == STATE_ON)
1412 *video_dev_info |= LCD_Device;
1413}
1414
1415static int get_primary_device(void) 1140static int get_primary_device(void)
1416{ 1141{
1417 int primary_device = 0; 1142 int primary_device = 0;
@@ -1453,18 +1178,6 @@ static int get_primary_device(void)
1453 return primary_device; 1178 return primary_device;
1454} 1179}
1455 1180
1456static u8 is_duoview(void)
1457{
1458 if (0 == viafb_SAMM_ON) {
1459 if (viafb_LCD_ON + viafb_LCD2_ON +
1460 viafb_DVI_ON + viafb_CRT_ON == 2)
1461 return true;
1462 return false;
1463 } else {
1464 return false;
1465 }
1466}
1467
1468static void apply_second_mode_setting(struct fb_var_screeninfo 1181static void apply_second_mode_setting(struct fb_var_screeninfo
1469 *sec_var) 1182 *sec_var)
1470{ 1183{
@@ -1566,14 +1279,13 @@ static int apply_device_setting(struct viafb_ioctl_setting setting_info,
1566 if (viafb_SAMM_ON) 1279 if (viafb_SAMM_ON)
1567 viafb_primary_dev = setting_info.primary_device; 1280 viafb_primary_dev = setting_info.primary_device;
1568 1281
1569 viafb_set_start_addr(); 1282 viafb_set_primary_address(0);
1283 viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
1570 viafb_set_iga_path(); 1284 viafb_set_iga_path();
1571 } 1285 }
1572 need_set_mode = 1; 1286 need_set_mode = 1;
1573 } 1287 }
1574 1288
1575 viaparinfo->duoview = is_duoview();
1576
1577 if (!need_set_mode) { 1289 if (!need_set_mode) {
1578 ; 1290 ;
1579 } else { 1291 } else {
@@ -1596,18 +1308,6 @@ static void retrieve_device_setting(struct viafb_ioctl_setting
1596 setting_info->device_status |= LCD_Device; 1308 setting_info->device_status |= LCD_Device;
1597 if (viafb_LCD2_ON == 1) 1309 if (viafb_LCD2_ON == 1)
1598 setting_info->device_status |= LCD2_Device; 1310 setting_info->device_status |= LCD2_Device;
1599 if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) {
1600 setting_info->video_device_status =
1601 viaparinfo->crt_setting_info->iga_path;
1602 } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) {
1603 setting_info->video_device_status =
1604 viaparinfo->tmds_setting_info->iga_path;
1605 } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) {
1606 setting_info->video_device_status =
1607 viaparinfo->lvds_setting_info->iga_path;
1608 } else {
1609 setting_info->video_device_status = 0;
1610 }
1611 1311
1612 setting_info->samm_status = viafb_SAMM_ON; 1312 setting_info->samm_status = viafb_SAMM_ON;
1613 setting_info->primary_device = get_primary_device(); 1313 setting_info->primary_device = get_primary_device();
@@ -1694,25 +1394,6 @@ static void parse_active_dev(void)
1694 viafb_CRT_ON = STATE_ON; 1394 viafb_CRT_ON = STATE_ON;
1695 viafb_SAMM_ON = STATE_OFF; 1395 viafb_SAMM_ON = STATE_OFF;
1696 } 1396 }
1697 viaparinfo->duoview = is_duoview();
1698}
1699
1700static void parse_video_dev(void)
1701{
1702 viaparinfo->video_on_crt = STATE_OFF;
1703 viaparinfo->video_on_dvi = STATE_OFF;
1704 viaparinfo->video_on_lcd = STATE_OFF;
1705
1706 if (!strncmp(viafb_video_dev, "CRT", 3)) {
1707 /* Video on CRT */
1708 viaparinfo->video_on_crt = STATE_ON;
1709 } else if (!strncmp(viafb_video_dev, "DVI", 3)) {
1710 /* Video on DVI */
1711 viaparinfo->video_on_dvi = STATE_ON;
1712 } else if (!strncmp(viafb_video_dev, "LCD", 3)) {
1713 /* Video on LCD */
1714 viaparinfo->video_on_lcd = STATE_ON;
1715 }
1716} 1397}
1717 1398
1718static int parse_port(char *opt_str, int *output_interface) 1399static int parse_port(char *opt_str, int *output_interface)
@@ -1761,10 +1442,8 @@ static void parse_dvi_port(void)
1761 * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], 1442 * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2],
1762 * CR9B, SR65, CR97, CR99 1443 * CR9B, SR65, CR97, CR99
1763 */ 1444 */
1764static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset, 1445static int viafb_dvp0_proc_show(struct seq_file *m, void *v)
1765int count, int *eof, void *data)
1766{ 1446{
1767 int len = 0;
1768 u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0; 1447 u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
1769 dvp0_data_dri = 1448 dvp0_data_dri =
1770 (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 | 1449 (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
@@ -1773,13 +1452,17 @@ int count, int *eof, void *data)
1773 (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 | 1452 (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
1774 (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2; 1453 (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
1775 dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f; 1454 dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
1776 len += 1455 seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
1777 sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri); 1456 return 0;
1778 *eof = 1; /*Inform kernel end of data */
1779 return len;
1780} 1457}
1781static int viafb_dvp0_proc_write(struct file *file, 1458
1782 const char __user *buffer, unsigned long count, void *data) 1459static int viafb_dvp0_proc_open(struct inode *inode, struct file *file)
1460{
1461 return single_open(file, viafb_dvp0_proc_show, NULL);
1462}
1463
1464static ssize_t viafb_dvp0_proc_write(struct file *file,
1465 const char __user *buffer, size_t count, loff_t *pos)
1783{ 1466{
1784 char buf[20], *value, *pbuf; 1467 char buf[20], *value, *pbuf;
1785 u8 reg_val = 0; 1468 u8 reg_val = 0;
@@ -1823,21 +1506,33 @@ static int viafb_dvp0_proc_write(struct file *file,
1823 } 1506 }
1824 return count; 1507 return count;
1825} 1508}
1826static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset, 1509
1827 int count, int *eof, void *data) 1510static const struct file_operations viafb_dvp0_proc_fops = {
1511 .owner = THIS_MODULE,
1512 .open = viafb_dvp0_proc_open,
1513 .read = seq_read,
1514 .llseek = seq_lseek,
1515 .release = single_release,
1516 .write = viafb_dvp0_proc_write,
1517};
1518
1519static int viafb_dvp1_proc_show(struct seq_file *m, void *v)
1828{ 1520{
1829 int len = 0;
1830 u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0; 1521 u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
1831 dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f; 1522 dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
1832 dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2; 1523 dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
1833 dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03; 1524 dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
1834 len += 1525 seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
1835 sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri); 1526 return 0;
1836 *eof = 1; /*Inform kernel end of data */
1837 return len;
1838} 1527}
1839static int viafb_dvp1_proc_write(struct file *file, 1528
1840 const char __user *buffer, unsigned long count, void *data) 1529static int viafb_dvp1_proc_open(struct inode *inode, struct file *file)
1530{
1531 return single_open(file, viafb_dvp1_proc_show, NULL);
1532}
1533
1534static ssize_t viafb_dvp1_proc_write(struct file *file,
1535 const char __user *buffer, size_t count, loff_t *pos)
1841{ 1536{
1842 char buf[20], *value, *pbuf; 1537 char buf[20], *value, *pbuf;
1843 u8 reg_val = 0; 1538 u8 reg_val = 0;
@@ -1876,18 +1571,30 @@ static int viafb_dvp1_proc_write(struct file *file,
1876 return count; 1571 return count;
1877} 1572}
1878 1573
1879static int viafb_dfph_proc_read(char *buf, char **start, off_t offset, 1574static const struct file_operations viafb_dvp1_proc_fops = {
1880 int count, int *eof, void *data) 1575 .owner = THIS_MODULE,
1576 .open = viafb_dvp1_proc_open,
1577 .read = seq_read,
1578 .llseek = seq_lseek,
1579 .release = single_release,
1580 .write = viafb_dvp1_proc_write,
1581};
1582
1583static int viafb_dfph_proc_show(struct seq_file *m, void *v)
1881{ 1584{
1882 int len = 0;
1883 u8 dfp_high = 0; 1585 u8 dfp_high = 0;
1884 dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f; 1586 dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
1885 len += sprintf(buf + len, "%x\n", dfp_high); 1587 seq_printf(m, "%x\n", dfp_high);
1886 *eof = 1; /*Inform kernel end of data */ 1588 return 0;
1887 return len;
1888} 1589}
1889static int viafb_dfph_proc_write(struct file *file, 1590
1890 const char __user *buffer, unsigned long count, void *data) 1591static int viafb_dfph_proc_open(struct inode *inode, struct file *file)
1592{
1593 return single_open(file, viafb_dfph_proc_show, NULL);
1594}
1595
1596static ssize_t viafb_dfph_proc_write(struct file *file,
1597 const char __user *buffer, size_t count, loff_t *pos)
1891{ 1598{
1892 char buf[20]; 1599 char buf[20];
1893 u8 reg_val = 0; 1600 u8 reg_val = 0;
@@ -1902,18 +1609,31 @@ static int viafb_dfph_proc_write(struct file *file,
1902 viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); 1609 viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
1903 return count; 1610 return count;
1904} 1611}
1905static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset, 1612
1906 int count, int *eof, void *data) 1613static const struct file_operations viafb_dfph_proc_fops = {
1614 .owner = THIS_MODULE,
1615 .open = viafb_dfph_proc_open,
1616 .read = seq_read,
1617 .llseek = seq_lseek,
1618 .release = single_release,
1619 .write = viafb_dfph_proc_write,
1620};
1621
1622static int viafb_dfpl_proc_show(struct seq_file *m, void *v)
1907{ 1623{
1908 int len = 0;
1909 u8 dfp_low = 0; 1624 u8 dfp_low = 0;
1910 dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f; 1625 dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
1911 len += sprintf(buf + len, "%x\n", dfp_low); 1626 seq_printf(m, "%x\n", dfp_low);
1912 *eof = 1; /*Inform kernel end of data */ 1627 return 0;
1913 return len;
1914} 1628}
1915static int viafb_dfpl_proc_write(struct file *file, 1629
1916 const char __user *buffer, unsigned long count, void *data) 1630static int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
1631{
1632 return single_open(file, viafb_dfpl_proc_show, NULL);
1633}
1634
1635static ssize_t viafb_dfpl_proc_write(struct file *file,
1636 const char __user *buffer, size_t count, loff_t *pos)
1917{ 1637{
1918 char buf[20]; 1638 char buf[20];
1919 u8 reg_val = 0; 1639 u8 reg_val = 0;
@@ -1928,10 +1648,18 @@ static int viafb_dfpl_proc_write(struct file *file,
1928 viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); 1648 viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
1929 return count; 1649 return count;
1930} 1650}
1931static int viafb_vt1636_proc_read(char *buf, char **start, 1651
1932 off_t offset, int count, int *eof, void *data) 1652static const struct file_operations viafb_dfpl_proc_fops = {
1653 .owner = THIS_MODULE,
1654 .open = viafb_dfpl_proc_open,
1655 .read = seq_read,
1656 .llseek = seq_lseek,
1657 .release = single_release,
1658 .write = viafb_dfpl_proc_write,
1659};
1660
1661static int viafb_vt1636_proc_show(struct seq_file *m, void *v)
1933{ 1662{
1934 int len = 0;
1935 u8 vt1636_08 = 0, vt1636_09 = 0; 1663 u8 vt1636_08 = 0, vt1636_09 = 0;
1936 switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { 1664 switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1937 case VT1636_LVDS: 1665 case VT1636_LVDS:
@@ -1941,7 +1669,7 @@ static int viafb_vt1636_proc_read(char *buf, char **start,
1941 vt1636_09 = 1669 vt1636_09 =
1942 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info, 1670 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1943 &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f; 1671 &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
1944 len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09); 1672 seq_printf(m, "%x %x\n", vt1636_08, vt1636_09);
1945 break; 1673 break;
1946 default: 1674 default:
1947 break; 1675 break;
@@ -1954,16 +1682,21 @@ static int viafb_vt1636_proc_read(char *buf, char **start,
1954 vt1636_09 = 1682 vt1636_09 =
1955 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2, 1683 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1956 &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f; 1684 &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
1957 len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09); 1685 seq_printf(m, " %x %x\n", vt1636_08, vt1636_09);
1958 break; 1686 break;
1959 default: 1687 default:
1960 break; 1688 break;
1961 } 1689 }
1962 *eof = 1; /*Inform kernel end of data */ 1690 return 0;
1963 return len;
1964} 1691}
1965static int viafb_vt1636_proc_write(struct file *file, 1692
1966 const char __user *buffer, unsigned long count, void *data) 1693static int viafb_vt1636_proc_open(struct inode *inode, struct file *file)
1694{
1695 return single_open(file, viafb_vt1636_proc_show, NULL);
1696}
1697
1698static ssize_t viafb_vt1636_proc_write(struct file *file,
1699 const char __user *buffer, size_t count, loff_t *pos)
1967{ 1700{
1968 char buf[30], *value, *pbuf; 1701 char buf[30], *value, *pbuf;
1969 struct IODATA reg_val; 1702 struct IODATA reg_val;
@@ -2052,39 +1785,27 @@ static int viafb_vt1636_proc_write(struct file *file,
2052 return count; 1785 return count;
2053} 1786}
2054 1787
1788static const struct file_operations viafb_vt1636_proc_fops = {
1789 .owner = THIS_MODULE,
1790 .open = viafb_vt1636_proc_open,
1791 .read = seq_read,
1792 .llseek = seq_lseek,
1793 .release = single_release,
1794 .write = viafb_vt1636_proc_write,
1795};
1796
2055static void viafb_init_proc(struct proc_dir_entry **viafb_entry) 1797static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
2056{ 1798{
2057 struct proc_dir_entry *entry;
2058 *viafb_entry = proc_mkdir("viafb", NULL); 1799 *viafb_entry = proc_mkdir("viafb", NULL);
2059 if (viafb_entry) { 1800 if (viafb_entry) {
2060 entry = create_proc_entry("dvp0", 0, *viafb_entry); 1801 proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
2061 if (entry) { 1802 proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
2062 entry->read_proc = viafb_dvp0_proc_read; 1803 proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
2063 entry->write_proc = viafb_dvp0_proc_write; 1804 proc_create("dfpl", 0, *viafb_entry, &viafb_dfpl_proc_fops);
2064 }
2065 entry = create_proc_entry("dvp1", 0, *viafb_entry);
2066 if (entry) {
2067 entry->read_proc = viafb_dvp1_proc_read;
2068 entry->write_proc = viafb_dvp1_proc_write;
2069 }
2070 entry = create_proc_entry("dfph", 0, *viafb_entry);
2071 if (entry) {
2072 entry->read_proc = viafb_dfph_proc_read;
2073 entry->write_proc = viafb_dfph_proc_write;
2074 }
2075 entry = create_proc_entry("dfpl", 0, *viafb_entry);
2076 if (entry) {
2077 entry->read_proc = viafb_dfpl_proc_read;
2078 entry->write_proc = viafb_dfpl_proc_write;
2079 }
2080 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. 1805 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
2081 lvds_chip_name || VT1636_LVDS == 1806 lvds_chip_name || VT1636_LVDS ==
2082 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { 1807 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2083 entry = create_proc_entry("vt1636", 0, *viafb_entry); 1808 proc_create("vt1636", 0, *viafb_entry, &viafb_vt1636_proc_fops);
2084 if (entry) {
2085 entry->read_proc = viafb_vt1636_proc_read;
2086 entry->write_proc = viafb_vt1636_proc_write;
2087 }
2088 } 1809 }
2089 1810
2090 } 1811 }
@@ -2101,51 +1822,61 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
2101 remove_proc_entry("viafb", NULL); 1822 remove_proc_entry("viafb", NULL);
2102} 1823}
2103 1824
2104static int __devinit via_pci_probe(void) 1825static void parse_mode(const char *str, u32 *xres, u32 *yres)
2105{ 1826{
2106 unsigned long default_xres, default_yres; 1827 char *ptr;
2107 char *tmpc, *tmpm; 1828
2108 char *tmpc_sec, *tmpm_sec; 1829 *xres = simple_strtoul(str, &ptr, 10);
1830 if (ptr[0] != 'x')
1831 goto out_default;
1832
1833 *yres = simple_strtoul(&ptr[1], &ptr, 10);
1834 if (ptr[0])
1835 goto out_default;
1836
1837 return;
1838
1839out_default:
1840 printk(KERN_WARNING "viafb received invalid mode string: %s\n", str);
1841 *xres = 640;
1842 *yres = 480;
1843}
1844
1845static int __devinit via_pci_probe(struct pci_dev *pdev,
1846 const struct pci_device_id *ent)
1847{
1848 u32 default_xres, default_yres;
2109 int vmode_index; 1849 int vmode_index;
2110 u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length; 1850 u32 viafb_par_length;
2111 1851
2112 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); 1852 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
2113 1853
2114 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); 1854 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
2115 tmds_length = ALIGN(sizeof(struct tmds_setting_information),
2116 BITS_PER_LONG/8);
2117 lvds_length = ALIGN(sizeof(struct lvds_setting_information),
2118 BITS_PER_LONG/8);
2119 crt_length = ALIGN(sizeof(struct lvds_setting_information),
2120 BITS_PER_LONG/8);
2121 chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8);
2122 1855
2123 /* Allocate fb_info and ***_par here, also including some other needed 1856 /* Allocate fb_info and ***_par here, also including some other needed
2124 * variables 1857 * variables
2125 */ 1858 */
2126 viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length + 1859 viafbinfo = framebuffer_alloc(viafb_par_length +
2127 tmds_length + crt_length + chip_length, NULL); 1860 ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
1861 &pdev->dev);
2128 if (!viafbinfo) { 1862 if (!viafbinfo) {
2129 printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); 1863 printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
2130 return -ENODEV; 1864 return -ENODEV;
2131 } 1865 }
2132 1866
2133 viaparinfo = (struct viafb_par *)viafbinfo->par; 1867 viaparinfo = (struct viafb_par *)viafbinfo->par;
2134 viaparinfo->tmds_setting_info = (struct tmds_setting_information *) 1868 viaparinfo->shared = viafbinfo->par + viafb_par_length;
2135 ((unsigned long)viaparinfo + viafb_par_length); 1869 viaparinfo->vram_addr = 0;
2136 viaparinfo->lvds_setting_info = (struct lvds_setting_information *) 1870 viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
2137 ((unsigned long)viaparinfo->tmds_setting_info + tmds_length); 1871 viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
2138 viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *) 1872 viaparinfo->lvds_setting_info2 =
2139 ((unsigned long)viaparinfo->lvds_setting_info + lvds_length); 1873 &viaparinfo->shared->lvds_setting_info2;
2140 viaparinfo->crt_setting_info = (struct crt_setting_information *) 1874 viaparinfo->crt_setting_info = &viaparinfo->shared->crt_setting_info;
2141 ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length); 1875 viaparinfo->chip_info = &viaparinfo->shared->chip_info;
2142 viaparinfo->chip_info = (struct chip_information *)
2143 ((unsigned long)viaparinfo->crt_setting_info + crt_length);
2144 1876
2145 if (viafb_dual_fb) 1877 if (viafb_dual_fb)
2146 viafb_SAMM_ON = 1; 1878 viafb_SAMM_ON = 1;
2147 parse_active_dev(); 1879 parse_active_dev();
2148 parse_video_dev();
2149 parse_lcd_port(); 1880 parse_lcd_port();
2150 parse_dvi_port(); 1881 parse_dvi_port();
2151 1882
@@ -2156,32 +1887,32 @@ static int __devinit via_pci_probe(void)
2156 /* Set up I2C bus stuff */ 1887 /* Set up I2C bus stuff */
2157 viafb_create_i2c_bus(viaparinfo); 1888 viafb_create_i2c_bus(viaparinfo);
2158 1889
2159 viafb_init_chip_info(); 1890 viafb_init_chip_info(pdev, ent);
2160 viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize); 1891 viaparinfo->fbmem = pci_resource_start(pdev, 0);
1892 viaparinfo->memsize = viafb_get_fb_size_from_pci();
2161 viaparinfo->fbmem_free = viaparinfo->memsize; 1893 viaparinfo->fbmem_free = viaparinfo->memsize;
2162 viaparinfo->fbmem_used = 0; 1894 viaparinfo->fbmem_used = 0;
2163 viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem, 1895 viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem,
2164 viaparinfo->memsize); 1896 viaparinfo->memsize);
2165 viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt; 1897 if (!viafbinfo->screen_base) {
2166
2167 if (!viaparinfo->fbmem_virt) {
2168 printk(KERN_INFO "ioremap failed\n"); 1898 printk(KERN_INFO "ioremap failed\n");
2169 return -1; 1899 return -ENOMEM;
2170 } 1900 }
2171 1901
2172 viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len); 1902 viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1);
2173 viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base, 1903 viafbinfo->fix.mmio_len = pci_resource_len(pdev, 1);
2174 viaparinfo->mmio_len);
2175
2176 viafbinfo->node = 0; 1904 viafbinfo->node = 0;
2177 viafbinfo->fbops = &viafb_ops; 1905 viafbinfo->fbops = &viafb_ops;
2178 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1906 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2179 1907
2180 viafbinfo->pseudo_palette = pseudo_pal; 1908 viafbinfo->pseudo_palette = pseudo_pal;
2181 if (viafb_accel) { 1909 if (viafb_accel && !viafb_init_engine(viafbinfo)) {
2182 viafb_init_accel(); 1910 viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
2183 viafb_init_2d_engine(); 1911 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
2184 viafb_hw_cursor_init(); 1912 default_var.accel_flags = FB_ACCELF_TEXT;
1913 } else {
1914 viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
1915 default_var.accel_flags = 0;
2185 } 1916 }
2186 1917
2187 if (viafb_second_size && (viafb_second_size < 8)) { 1918 if (viafb_second_size && (viafb_second_size < 8)) {
@@ -2193,27 +1924,14 @@ static int __devinit via_pci_probe(void)
2193 viafb_second_size * 1024 * 1024; 1924 viafb_second_size * 1024 * 1024;
2194 } 1925 }
2195 1926
2196 viafb_FB_MM = viaparinfo->fbmem_virt; 1927 parse_mode(viafb_mode, &default_xres, &default_yres);
2197 tmpm = viafb_mode; 1928 vmode_index = viafb_get_mode_index(default_xres, default_yres);
2198 tmpc = strsep(&tmpm, "x");
2199 strict_strtoul(tmpc, 0, &default_xres);
2200 strict_strtoul(tmpm, 0, &default_yres);
2201
2202 vmode_index = viafb_get_mode_index(default_xres, default_yres, 0);
2203 DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); 1929 DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
2204 1930
2205 if (viafb_SAMM_ON == 1) { 1931 if (viafb_SAMM_ON == 1) {
2206 if (strcmp(viafb_mode, viafb_mode1)) { 1932 parse_mode(viafb_mode1, &viafb_second_xres,
2207 tmpm_sec = viafb_mode1; 1933 &viafb_second_yres);
2208 tmpc_sec = strsep(&tmpm_sec, "x"); 1934
2209 strict_strtoul(tmpc_sec, 0,
2210 (unsigned long *)&viafb_second_xres);
2211 strict_strtoul(tmpm_sec, 0,
2212 (unsigned long *)&viafb_second_yres);
2213 } else {
2214 viafb_second_xres = default_xres;
2215 viafb_second_yres = default_yres;
2216 }
2217 if (0 == viafb_second_virtual_xres) { 1935 if (0 == viafb_second_virtual_xres) {
2218 switch (viafb_second_xres) { 1936 switch (viafb_second_xres) {
2219 case 1400: 1937 case 1400:
@@ -2263,18 +1981,9 @@ static int __devinit via_pci_probe(void)
2263 default_var.lower_margin = 4; 1981 default_var.lower_margin = 4;
2264 default_var.hsync_len = default_var.left_margin; 1982 default_var.hsync_len = default_var.left_margin;
2265 default_var.vsync_len = 4; 1983 default_var.vsync_len = 4;
2266 default_var.accel_flags = 0;
2267
2268 if (viafb_accel) {
2269 viafbinfo->flags |=
2270 (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
2271 FBINFO_HWACCEL_IMAGEBLIT);
2272 default_var.accel_flags |= FB_ACCELF_TEXT;
2273 } else
2274 viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
2275 1984
2276 if (viafb_dual_fb) { 1985 if (viafb_dual_fb) {
2277 viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL); 1986 viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev);
2278 if (!viafbinfo1) { 1987 if (!viafbinfo1) {
2279 printk(KERN_ERR 1988 printk(KERN_ERR
2280 "allocate the second framebuffer struct error\n"); 1989 "allocate the second framebuffer struct error\n");
@@ -2283,11 +1992,10 @@ static int __devinit via_pci_probe(void)
2283 } 1992 }
2284 viaparinfo1 = viafbinfo1->par; 1993 viaparinfo1 = viafbinfo1->par;
2285 memcpy(viaparinfo1, viaparinfo, viafb_par_length); 1994 memcpy(viaparinfo1, viaparinfo, viafb_par_length);
1995 viaparinfo1->vram_addr = viafb_second_offset;
2286 viaparinfo1->memsize = viaparinfo->memsize - 1996 viaparinfo1->memsize = viaparinfo->memsize -
2287 viafb_second_offset; 1997 viafb_second_offset;
2288 viaparinfo->memsize = viafb_second_offset; 1998 viaparinfo->memsize = viafb_second_offset;
2289 viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt +
2290 viafb_second_offset;
2291 viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset; 1999 viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
2292 2000
2293 viaparinfo1->fbmem_used = viaparinfo->fbmem_used; 2001 viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
@@ -2295,20 +2003,13 @@ static int __devinit via_pci_probe(void)
2295 viaparinfo1->fbmem_used; 2003 viaparinfo1->fbmem_used;
2296 viaparinfo->fbmem_free = viaparinfo->memsize; 2004 viaparinfo->fbmem_free = viaparinfo->memsize;
2297 viaparinfo->fbmem_used = 0; 2005 viaparinfo->fbmem_used = 0;
2298 if (viafb_accel) {
2299 viaparinfo1->cursor_start =
2300 viaparinfo->cursor_start - viafb_second_offset;
2301 viaparinfo1->VQ_start = viaparinfo->VQ_start -
2302 viafb_second_offset;
2303 viaparinfo1->VQ_end = viaparinfo->VQ_end -
2304 viafb_second_offset;
2305 }
2306 2006
2007 viaparinfo->iga_path = IGA1;
2008 viaparinfo1->iga_path = IGA2;
2307 memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info)); 2009 memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
2010 viafbinfo1->par = viaparinfo1;
2308 viafbinfo1->screen_base = viafbinfo->screen_base + 2011 viafbinfo1->screen_base = viafbinfo->screen_base +
2309 viafb_second_offset; 2012 viafb_second_offset;
2310 viafbinfo1->fix.smem_start = viaparinfo1->fbmem;
2311 viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free;
2312 2013
2313 default_var.xres = viafb_second_xres; 2014 default_var.xres = viafb_second_xres;
2314 default_var.yres = viafb_second_yres; 2015 default_var.yres = viafb_second_yres;
@@ -2330,15 +2031,17 @@ static int __devinit via_pci_probe(void)
2330 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); 2031 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
2331 viafb_check_var(&default_var, viafbinfo1); 2032 viafb_check_var(&default_var, viafbinfo1);
2332 viafbinfo1->var = default_var; 2033 viafbinfo1->var = default_var;
2333 viafb_update_viafb_par(viafbinfo); 2034 viafb_update_fix(viafbinfo1);
2334 viafb_update_fix(&viafbinfo1->fix, viafbinfo1); 2035 viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
2036 &viafbinfo1->fix);
2335 } 2037 }
2336 2038
2337 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); 2039 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
2338 viafb_check_var(&default_var, viafbinfo); 2040 viafb_check_var(&default_var, viafbinfo);
2339 viafbinfo->var = default_var; 2041 viafbinfo->var = default_var;
2340 viafb_update_viafb_par(viafbinfo); 2042 viafb_update_fix(viafbinfo);
2341 viafb_update_fix(&viafbinfo->fix, viafbinfo); 2043 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
2044 &viafbinfo->fix);
2342 default_var.activate = FB_ACTIVATE_NOW; 2045 default_var.activate = FB_ACTIVATE_NOW;
2343 fb_alloc_cmap(&viafbinfo->cmap, 256, 0); 2046 fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
2344 2047
@@ -2360,20 +2063,20 @@ static int __devinit via_pci_probe(void)
2360 viafbinfo->node, viafbinfo->fix.id, default_var.xres, 2063 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
2361 default_var.yres, default_var.bits_per_pixel); 2064 default_var.yres, default_var.bits_per_pixel);
2362 2065
2363 viafb_init_proc(&viaparinfo->proc_entry); 2066 viafb_init_proc(&viaparinfo->shared->proc_entry);
2364 viafb_init_dac(IGA2); 2067 viafb_init_dac(IGA2);
2365 return 0; 2068 return 0;
2366} 2069}
2367 2070
2368static void __devexit via_pci_remove(void) 2071static void __devexit via_pci_remove(struct pci_dev *pdev)
2369{ 2072{
2370 DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); 2073 DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
2371 fb_dealloc_cmap(&viafbinfo->cmap); 2074 fb_dealloc_cmap(&viafbinfo->cmap);
2372 unregister_framebuffer(viafbinfo); 2075 unregister_framebuffer(viafbinfo);
2373 if (viafb_dual_fb) 2076 if (viafb_dual_fb)
2374 unregister_framebuffer(viafbinfo1); 2077 unregister_framebuffer(viafbinfo1);
2375 iounmap((void *)viaparinfo->fbmem_virt); 2078 iounmap((void *)viafbinfo->screen_base);
2376 iounmap(viaparinfo->io_virt); 2079 iounmap(viaparinfo->shared->engine_mmio);
2377 2080
2378 viafb_delete_i2c_buss(viaparinfo); 2081 viafb_delete_i2c_buss(viaparinfo);
2379 2082
@@ -2381,7 +2084,7 @@ static void __devexit via_pci_remove(void)
2381 if (viafb_dual_fb) 2084 if (viafb_dual_fb)
2382 framebuffer_release(viafbinfo1); 2085 framebuffer_release(viafbinfo1);
2383 2086
2384 viafb_remove_proc(viaparinfo->proc_entry); 2087 viafb_remove_proc(viaparinfo->shared->proc_entry);
2385} 2088}
2386 2089
2387#ifndef MODULE 2090#ifndef MODULE
@@ -2448,8 +2151,6 @@ static int __init viafb_setup(char *options)
2448 else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) 2151 else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
2449 strict_strtoul(this_opt + 15, 0, 2152 strict_strtoul(this_opt + 15, 0,
2450 (unsigned long *)&viafb_lcd_mode); 2153 (unsigned long *)&viafb_lcd_mode);
2451 else if (!strncmp(this_opt, "viafb_video_dev=", 16))
2452 viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL);
2453 else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) 2154 else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
2454 viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); 2155 viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
2455 else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) 2156 else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
@@ -2459,6 +2160,40 @@ static int __init viafb_setup(char *options)
2459} 2160}
2460#endif 2161#endif
2461 2162
2163static struct pci_device_id viafb_pci_table[] __devinitdata = {
2164 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
2165 .driver_data = UNICHROME_CLE266 },
2166 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
2167 .driver_data = UNICHROME_PM800 },
2168 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
2169 .driver_data = UNICHROME_K400 },
2170 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
2171 .driver_data = UNICHROME_K800 },
2172 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
2173 .driver_data = UNICHROME_CN700 },
2174 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
2175 .driver_data = UNICHROME_K8M890 },
2176 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
2177 .driver_data = UNICHROME_CX700 },
2178 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
2179 .driver_data = UNICHROME_P4M900 },
2180 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
2181 .driver_data = UNICHROME_CN750 },
2182 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
2183 .driver_data = UNICHROME_VX800 },
2184 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
2185 .driver_data = UNICHROME_VX855 },
2186 { }
2187};
2188MODULE_DEVICE_TABLE(pci, viafb_pci_table);
2189
2190static struct pci_driver viafb_driver = {
2191 .name = "viafb",
2192 .id_table = viafb_pci_table,
2193 .probe = via_pci_probe,
2194 .remove = __devexit_p(via_pci_remove),
2195};
2196
2462static int __init viafb_init(void) 2197static int __init viafb_init(void)
2463{ 2198{
2464#ifndef MODULE 2199#ifndef MODULE
@@ -2470,13 +2205,13 @@ static int __init viafb_init(void)
2470 printk(KERN_INFO 2205 printk(KERN_INFO
2471 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", 2206 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
2472 VERSION_MAJOR, VERSION_MINOR); 2207 VERSION_MAJOR, VERSION_MINOR);
2473 return via_pci_probe(); 2208 return pci_register_driver(&viafb_driver);
2474} 2209}
2475 2210
2476static void __exit viafb_exit(void) 2211static void __exit viafb_exit(void)
2477{ 2212{
2478 DEBUG_MSG(KERN_INFO "viafb_exit!\n"); 2213 DEBUG_MSG(KERN_INFO "viafb_exit!\n");
2479 via_pci_remove(); 2214 pci_unregister_driver(&viafb_driver);
2480} 2215}
2481 2216
2482static struct fb_ops viafb_ops = { 2217static struct fb_ops viafb_ops = {
@@ -2501,82 +2236,79 @@ module_init(viafb_init);
2501module_exit(viafb_exit); 2236module_exit(viafb_exit);
2502 2237
2503#ifdef MODULE 2238#ifdef MODULE
2504module_param(viafb_memsize, int, 0); 2239module_param(viafb_memsize, int, S_IRUSR);
2505 2240
2506module_param(viafb_mode, charp, 0); 2241module_param(viafb_mode, charp, S_IRUSR);
2507MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); 2242MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
2508 2243
2509module_param(viafb_mode1, charp, 0); 2244module_param(viafb_mode1, charp, S_IRUSR);
2510MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)"); 2245MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
2511 2246
2512module_param(viafb_bpp, int, 0); 2247module_param(viafb_bpp, int, S_IRUSR);
2513MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)"); 2248MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
2514 2249
2515module_param(viafb_bpp1, int, 0); 2250module_param(viafb_bpp1, int, S_IRUSR);
2516MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)"); 2251MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
2517 2252
2518module_param(viafb_refresh, int, 0); 2253module_param(viafb_refresh, int, S_IRUSR);
2519MODULE_PARM_DESC(viafb_refresh, 2254MODULE_PARM_DESC(viafb_refresh,
2520 "Set CRT viafb_refresh rate (default = 60)"); 2255 "Set CRT viafb_refresh rate (default = 60)");
2521 2256
2522module_param(viafb_refresh1, int, 0); 2257module_param(viafb_refresh1, int, S_IRUSR);
2523MODULE_PARM_DESC(viafb_refresh1, 2258MODULE_PARM_DESC(viafb_refresh1,
2524 "Set CRT refresh rate (default = 60)"); 2259 "Set CRT refresh rate (default = 60)");
2525 2260
2526module_param(viafb_lcd_panel_id, int, 0); 2261module_param(viafb_lcd_panel_id, int, S_IRUSR);
2527MODULE_PARM_DESC(viafb_lcd_panel_id, 2262MODULE_PARM_DESC(viafb_lcd_panel_id,
2528 "Set Flat Panel type(Default=1024x768)"); 2263 "Set Flat Panel type(Default=1024x768)");
2529 2264
2530module_param(viafb_lcd_dsp_method, int, 0); 2265module_param(viafb_lcd_dsp_method, int, S_IRUSR);
2531MODULE_PARM_DESC(viafb_lcd_dsp_method, 2266MODULE_PARM_DESC(viafb_lcd_dsp_method,
2532 "Set Flat Panel display scaling method.(Default=Expandsion)"); 2267 "Set Flat Panel display scaling method.(Default=Expandsion)");
2533 2268
2534module_param(viafb_SAMM_ON, int, 0); 2269module_param(viafb_SAMM_ON, int, S_IRUSR);
2535MODULE_PARM_DESC(viafb_SAMM_ON, 2270MODULE_PARM_DESC(viafb_SAMM_ON,
2536 "Turn on/off flag of SAMM(Default=OFF)"); 2271 "Turn on/off flag of SAMM(Default=OFF)");
2537 2272
2538module_param(viafb_accel, int, 0); 2273module_param(viafb_accel, int, S_IRUSR);
2539MODULE_PARM_DESC(viafb_accel, 2274MODULE_PARM_DESC(viafb_accel,
2540 "Set 2D Hardware Acceleration.(Default = OFF)"); 2275 "Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)");
2541 2276
2542module_param(viafb_active_dev, charp, 0); 2277module_param(viafb_active_dev, charp, S_IRUSR);
2543MODULE_PARM_DESC(viafb_active_dev, "Specify active devices."); 2278MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
2544 2279
2545module_param(viafb_display_hardware_layout, int, 0); 2280module_param(viafb_display_hardware_layout, int, S_IRUSR);
2546MODULE_PARM_DESC(viafb_display_hardware_layout, 2281MODULE_PARM_DESC(viafb_display_hardware_layout,
2547 "Display Hardware Layout (LCD Only, DVI Only...,etc)"); 2282 "Display Hardware Layout (LCD Only, DVI Only...,etc)");
2548 2283
2549module_param(viafb_second_size, int, 0); 2284module_param(viafb_second_size, int, S_IRUSR);
2550MODULE_PARM_DESC(viafb_second_size, 2285MODULE_PARM_DESC(viafb_second_size,
2551 "Set secondary device memory size"); 2286 "Set secondary device memory size");
2552 2287
2553module_param(viafb_dual_fb, int, 0); 2288module_param(viafb_dual_fb, int, S_IRUSR);
2554MODULE_PARM_DESC(viafb_dual_fb, 2289MODULE_PARM_DESC(viafb_dual_fb,
2555 "Turn on/off flag of dual framebuffer devices.(Default = OFF)"); 2290 "Turn on/off flag of dual framebuffer devices.(Default = OFF)");
2556 2291
2557module_param(viafb_platform_epia_dvi, int, 0); 2292module_param(viafb_platform_epia_dvi, int, S_IRUSR);
2558MODULE_PARM_DESC(viafb_platform_epia_dvi, 2293MODULE_PARM_DESC(viafb_platform_epia_dvi,
2559 "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)"); 2294 "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
2560 2295
2561module_param(viafb_device_lcd_dualedge, int, 0); 2296module_param(viafb_device_lcd_dualedge, int, S_IRUSR);
2562MODULE_PARM_DESC(viafb_device_lcd_dualedge, 2297MODULE_PARM_DESC(viafb_device_lcd_dualedge,
2563 "Turn on/off flag of dual edge panel.(Default = OFF)"); 2298 "Turn on/off flag of dual edge panel.(Default = OFF)");
2564 2299
2565module_param(viafb_bus_width, int, 0); 2300module_param(viafb_bus_width, int, S_IRUSR);
2566MODULE_PARM_DESC(viafb_bus_width, 2301MODULE_PARM_DESC(viafb_bus_width,
2567 "Set bus width of panel.(Default = 12)"); 2302 "Set bus width of panel.(Default = 12)");
2568 2303
2569module_param(viafb_lcd_mode, int, 0); 2304module_param(viafb_lcd_mode, int, S_IRUSR);
2570MODULE_PARM_DESC(viafb_lcd_mode, 2305MODULE_PARM_DESC(viafb_lcd_mode,
2571 "Set Flat Panel mode(Default=OPENLDI)"); 2306 "Set Flat Panel mode(Default=OPENLDI)");
2572 2307
2573module_param(viafb_video_dev, charp, 0); 2308module_param(viafb_lcd_port, charp, S_IRUSR);
2574MODULE_PARM_DESC(viafb_video_dev, "Specify video devices.");
2575
2576module_param(viafb_lcd_port, charp, 0);
2577MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port."); 2309MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
2578 2310
2579module_param(viafb_dvi_port, charp, 0); 2311module_param(viafb_dvi_port, charp, S_IRUSR);
2580MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port."); 2312MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
2581 2313
2582MODULE_LICENSE("GPL"); 2314MODULE_LICENSE("GPL");
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index a4158e872878..0c94d2441922 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -37,52 +37,50 @@
37#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */ 37#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */
38#define VERSION_MINOR 4 38#define VERSION_MINOR 4
39 39
40struct viafb_shared {
41 struct proc_dir_entry *proc_entry; /*viafb proc entry */
42
43 /* I2C stuff */
44 struct via_i2c_stuff i2c_stuff;
45
46 /* All the information will be needed to set engine */
47 struct tmds_setting_information tmds_setting_info;
48 struct crt_setting_information crt_setting_info;
49 struct lvds_setting_information lvds_setting_info;
50 struct lvds_setting_information lvds_setting_info2;
51 struct chip_information chip_info;
52
53 /* hardware acceleration stuff */
54 void __iomem *engine_mmio;
55 u32 cursor_vram_addr;
56 u32 vq_vram_addr; /* virtual queue address in video ram */
57 int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height,
58 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
59 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
60 u32 fg_color, u32 bg_color, u8 fill_rop);
61};
62
40struct viafb_par { 63struct viafb_par {
41 int bpp; 64 u8 depth;
42 int hres; 65 u32 vram_addr;
43 int vres; 66
44 int linelength;
45 u32 xoffset;
46 u32 yoffset;
47
48 void __iomem *fbmem_virt; /*framebuffer virtual memory address */
49 void __iomem *io_virt; /*iospace virtual memory address */
50 unsigned int fbmem; /*framebuffer physical memory address */ 67 unsigned int fbmem; /*framebuffer physical memory address */
51 unsigned int memsize; /*size of fbmem */ 68 unsigned int memsize; /*size of fbmem */
52 unsigned int io; /*io space address */
53 unsigned long mmio_base; /*mmio base address */
54 unsigned long mmio_len; /*mmio base length */
55 u32 fbmem_free; /* Free FB memory */ 69 u32 fbmem_free; /* Free FB memory */
56 u32 fbmem_used; /* Use FB memory size */ 70 u32 fbmem_used; /* Use FB memory size */
57 u32 cursor_start; /* Cursor Start Address */
58 u32 VQ_start; /* Virtual Queue Start Address */
59 u32 VQ_end; /* Virtual Queue End Address */
60 u32 iga_path; 71 u32 iga_path;
61 struct proc_dir_entry *proc_entry; /*viafb proc entry */
62 u8 duoview; /*Is working in duoview mode? */
63 72
64 /* I2C stuff */ 73 struct viafb_shared *shared;
65 struct via_i2c_stuff i2c_stuff;
66 74
67 /* All the information will be needed to set engine */ 75 /* All the information will be needed to set engine */
76 /* depreciated, use the ones in shared directly */
68 struct tmds_setting_information *tmds_setting_info; 77 struct tmds_setting_information *tmds_setting_info;
69 struct crt_setting_information *crt_setting_info; 78 struct crt_setting_information *crt_setting_info;
70 struct lvds_setting_information *lvds_setting_info; 79 struct lvds_setting_information *lvds_setting_info;
71 struct lvds_setting_information *lvds_setting_info2; 80 struct lvds_setting_information *lvds_setting_info2;
72 struct chip_information *chip_info; 81 struct chip_information *chip_info;
73
74 /* some information related to video playing */
75 int video_on_crt;
76 int video_on_dvi;
77 int video_on_lcd;
78
79};
80struct viafb_modeinfo {
81 u32 xres;
82 u32 yres;
83 int mode_index;
84 char *mode_res;
85}; 82};
83
86extern unsigned int viafb_second_virtual_yres; 84extern unsigned int viafb_second_virtual_yres;
87extern unsigned int viafb_second_virtual_xres; 85extern unsigned int viafb_second_virtual_xres;
88extern unsigned int viafb_second_offset; 86extern unsigned int viafb_second_offset;
@@ -92,17 +90,15 @@ extern int viafb_dual_fb;
92extern int viafb_LCD2_ON; 90extern int viafb_LCD2_ON;
93extern int viafb_LCD_ON; 91extern int viafb_LCD_ON;
94extern int viafb_DVI_ON; 92extern int viafb_DVI_ON;
95extern int viafb_accel;
96extern int viafb_hotplug; 93extern int viafb_hotplug;
97extern int viafb_memsize; 94extern int viafb_memsize;
98 95
99extern int strict_strtoul(const char *cp, unsigned int base, 96extern int strict_strtoul(const char *cp, unsigned int base,
100 unsigned long *res); 97 unsigned long *res);
101 98
102void viafb_memory_pitch_patch(struct fb_info *info);
103void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 99void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
104 int mode_index); 100 int mode_index);
105int viafb_get_mode_index(int hres, int vres, int flag); 101int viafb_get_mode_index(int hres, int vres);
106u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information 102u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
107 *plvds_setting_info, struct lvds_chip_information 103 *plvds_setting_info, struct lvds_chip_information
108 *plvds_chip_info, u8 index); 104 *plvds_chip_info, u8 index);
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 6dcf583a837d..b74f8a67923c 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -100,12 +100,8 @@ struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
100{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ 100{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
101{VIACR, CR32, 0xFF, 0x00}, 101{VIACR, CR32, 0xFF, 0x00},
102{VIACR, CR33, 0xFF, 0x00}, 102{VIACR, CR33, 0xFF, 0x00},
103{VIACR, CR34, 0xFF, 0x00},
104{VIACR, CR35, 0xFF, 0x00}, 103{VIACR, CR35, 0xFF, 0x00},
105{VIACR, CR36, 0x08, 0x00}, 104{VIACR, CR36, 0x08, 0x00},
106{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
107{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
108{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
109{VIACR, CR69, 0xFF, 0x00}, 105{VIACR, CR69, 0xFF, 0x00},
110{VIACR, CR6A, 0xFF, 0x40}, 106{VIACR, CR6A, 0xFF, 0x40},
111{VIACR, CR6B, 0xFF, 0x00}, 107{VIACR, CR6B, 0xFF, 0x00},
@@ -159,16 +155,12 @@ struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
159{VIASR, CR30, 0xFF, 0x04}, 155{VIASR, CR30, 0xFF, 0x04},
160{VIACR, CR32, 0xFF, 0x00}, 156{VIACR, CR32, 0xFF, 0x00},
161{VIACR, CR33, 0x7F, 0x00}, 157{VIACR, CR33, 0x7F, 0x00},
162{VIACR, CR34, 0xFF, 0x00},
163{VIACR, CR35, 0xFF, 0x00}, 158{VIACR, CR35, 0xFF, 0x00},
164{VIACR, CR36, 0xFF, 0x31}, 159{VIACR, CR36, 0xFF, 0x31},
165{VIACR, CR41, 0xFF, 0x80}, 160{VIACR, CR41, 0xFF, 0x80},
166{VIACR, CR42, 0xFF, 0x00}, 161{VIACR, CR42, 0xFF, 0x00},
167{VIACR, CR55, 0x80, 0x00}, 162{VIACR, CR55, 0x80, 0x00},
168{VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/ 163{VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/
169{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
170{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
171{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
172{VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ 164{VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
173{VIACR, CR69, 0xFF, 0x00}, 165{VIACR, CR69, 0xFF, 0x00},
174{VIACR, CR6A, 0xFD, 0x40}, 166{VIACR, CR6A, 0xFD, 0x40},
@@ -233,9 +225,6 @@ struct io_reg KM400_ModeXregs[] = {
233 {VIACR, CR55, 0x80, 0x00}, 225 {VIACR, CR55, 0x80, 0x00},
234 {VIACR, CR5D, 0x80, 0x00}, 226 {VIACR, CR5D, 0x80, 0x00},
235 {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */ 227 {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */
236 {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
237 {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
238 {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
239 {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */ 228 {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
240 {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */ 229 {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */
241 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ 230 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
@@ -285,14 +274,9 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
285{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ 274{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
286{VIACR, CR32, 0xFF, 0x00}, 275{VIACR, CR32, 0xFF, 0x00},
287{VIACR, CR33, 0xFF, 0x00}, 276{VIACR, CR33, 0xFF, 0x00},
288{VIACR, CR34, 0xFF, 0x00},
289{VIACR, CR35, 0xFF, 0x00}, 277{VIACR, CR35, 0xFF, 0x00},
290{VIACR, CR36, 0x08, 0x00}, 278{VIACR, CR36, 0x08, 0x00},
291{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */ 279{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
292{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
293{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
294{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
295{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
296{VIACR, CR69, 0xFF, 0x00}, 280{VIACR, CR69, 0xFF, 0x00},
297{VIACR, CR6A, 0xFF, 0x40}, 281{VIACR, CR6A, 0xFF, 0x40},
298{VIACR, CR6B, 0xFF, 0x00}, 282{VIACR, CR6B, 0xFF, 0x00},
@@ -325,69 +309,61 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
325{VIACR, CR96, 0xFF, 0x00}, 309{VIACR, CR96, 0xFF, 0x00},
326{VIACR, CR97, 0xFF, 0x00}, 310{VIACR, CR97, 0xFF, 0x00},
327{VIACR, CR99, 0xFF, 0x00}, 311{VIACR, CR99, 0xFF, 0x00},
328{VIACR, CR9B, 0xFF, 0x00}, 312{VIACR, CR9B, 0xFF, 0x00}
329{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
330}; 313};
331 314
332/* For VT3353: Common Setting for Video Mode */ 315struct io_reg VX855_ModeXregs[] = {
333struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01}, 316{VIASR, SR10, 0xFF, 0x01},
334{VIASR, SR15, 0x02, 0x02}, 317{VIASR, SR15, 0x02, 0x02},
335{VIASR, SR16, 0xBF, 0x08}, 318{VIASR, SR16, 0xBF, 0x08},
336{VIASR, SR17, 0xFF, 0x1F}, 319{VIASR, SR17, 0xFF, 0x1F},
337{VIASR, SR18, 0xFF, 0x4E}, 320{VIASR, SR18, 0xFF, 0x4E},
338{VIASR, SR1A, 0xFB, 0x08}, 321{VIASR, SR1A, 0xFB, 0x08},
339{VIASR, SR1B, 0xFF, 0xF0}, 322{VIASR, SR1B, 0xFF, 0xF0},
340{VIASR, SR1E, 0xFF, 0x01}, 323{VIASR, SR1E, 0x07, 0x01},
341{VIASR, SR2A, 0xFF, 0x00}, 324{VIASR, SR2A, 0xF0, 0x00},
325{VIASR, SR58, 0xFF, 0x00},
326{VIASR, SR59, 0xFF, 0x00},
342{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */ 327{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
328{VIACR, CR09, 0xFF, 0x00}, /* Initial CR09=0*/
329{VIACR, CR11, 0x8F, 0x00}, /* IGA1 initial Vertical end */
330{VIACR, CR17, 0x7F, 0x00}, /* IGA1 CRT Mode control init */
343{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */ 331{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
344{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */ 332{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
345{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */ 333{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
346{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */ 334{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
347{VIACR, CR32, 0xFF, 0x00}, 335{VIACR, CR32, 0xFF, 0x00},
348{VIACR, CR33, 0xFF, 0x00}, 336{VIACR, CR33, 0x7F, 0x00},
349{VIACR, CR34, 0xFF, 0x00},
350{VIACR, CR35, 0xFF, 0x00}, 337{VIACR, CR35, 0xFF, 0x00},
351{VIACR, CR36, 0x08, 0x00}, 338{VIACR, CR36, 0x08, 0x00},
352{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
353{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
354{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
355{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
356{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
357{VIACR, CR69, 0xFF, 0x00}, 339{VIACR, CR69, 0xFF, 0x00},
358{VIACR, CR6A, 0xFF, 0x40}, 340{VIACR, CR6A, 0xFD, 0x60},
359{VIACR, CR6B, 0xFF, 0x00}, 341{VIACR, CR6B, 0xFF, 0x00},
360{VIACR, CR6C, 0xFF, 0x00}, 342{VIACR, CR6C, 0xFF, 0x00},
361{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ 343{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
362{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ 344{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
363{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ 345{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
364{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ 346{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
365{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ 347{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
366{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ 348{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
367{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ 349{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
368{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ 350{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
369{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ 351{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
370{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ 352{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
371{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ 353{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
372{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ 354{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
373{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ 355{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
374{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ 356{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
375{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */ 357{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
376{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */ 358{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
377{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */ 359{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
378{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */ 360{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
379{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */ 361{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
380{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
381{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
382{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
383{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
384{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
385{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
386{VIACR, CR96, 0xFF, 0x00}, 362{VIACR, CR96, 0xFF, 0x00},
387{VIACR, CR97, 0xFF, 0x00}, 363{VIACR, CR97, 0xFF, 0x00},
388{VIACR, CR99, 0xFF, 0x00}, 364{VIACR, CR99, 0xFF, 0x00},
389{VIACR, CR9B, 0xFF, 0x00}, 365{VIACR, CR9B, 0xFF, 0x00},
390{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */ 366{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
391}; 367};
392 368
393/* Video Mode Table */ 369/* Video Mode Table */
@@ -401,7 +377,6 @@ struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
401{VIASR, SR1A, 0xFB, 0x08}, 377{VIASR, SR1A, 0xFB, 0x08},
402 378
403{VIACR, CR32, 0xFF, 0x00}, 379{VIACR, CR32, 0xFF, 0x00},
404{VIACR, CR34, 0xFF, 0x00},
405{VIACR, CR35, 0xFF, 0x00}, 380{VIACR, CR35, 0xFF, 0x00},
406{VIACR, CR36, 0x08, 0x00}, 381{VIACR, CR36, 0x08, 0x00},
407{VIACR, CR6A, 0xFF, 0x80}, 382{VIACR, CR6A, 0xFF, 0x80},
@@ -1084,3 +1059,14 @@ struct VideoModeTable CEA_HDMI_Modes[] = {
1084 {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, 1059 {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
1085 {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} 1060 {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
1086}; 1061};
1062
1063int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl);
1064int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes);
1065int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
1066int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
1067int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
1068int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs);
1069int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs);
1070int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
1071int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
1072int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes);
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 1a5de50a23a2..a9d6554fabdf 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -50,128 +50,35 @@ struct res_map_refresh {
50 int vmode_refresh; 50 int vmode_refresh;
51}; 51};
52 52
53#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl) 53extern int NUM_TOTAL_RES_MAP_REFRESH;
54#define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes) 54extern int NUM_TOTAL_CEA_MODES;
55#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs) 55extern int NUM_TOTAL_CN400_ModeXregs;
56#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs) 56extern int NUM_TOTAL_CN700_ModeXregs;
57#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs) 57extern int NUM_TOTAL_KM400_ModeXregs;
58#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs) 58extern int NUM_TOTAL_CX700_ModeXregs;
59#define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs) 59extern int NUM_TOTAL_VX855_ModeXregs;
60#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs) 60extern int NUM_TOTAL_CLE266_ModeXregs;
61#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table) 61extern int NUM_TOTAL_PATCH_MODE;
62#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes) 62extern int NUM_TOTAL_MODETABLE;
63 63
64/********************/ 64/********************/
65/* Mode Table */ 65/* Mode Table */
66/********************/ 66/********************/
67 67
68/* 480x640 */ 68extern struct VideoModeTable CLE266Modes[];
69extern struct crt_mode_table CRTM480x640[1]; 69extern struct crt_mode_table CEAM1280x720[];
70/* 640x480*/ 70extern struct crt_mode_table CEAM1920x1080[];
71extern struct crt_mode_table CRTM640x480[5]; 71extern struct VideoModeTable CEA_HDMI_Modes[];
72/*720x480 (GTF)*/
73extern struct crt_mode_table CRTM720x480[1];
74/*720x576 (GTF)*/
75extern struct crt_mode_table CRTM720x576[1];
76/* 800x480 (CVT) */
77extern struct crt_mode_table CRTM800x480[1];
78/* 800x600*/
79extern struct crt_mode_table CRTM800x600[5];
80/* 848x480 (CVT) */
81extern struct crt_mode_table CRTM848x480[1];
82/*856x480 (GTF) convert to 852x480*/
83extern struct crt_mode_table CRTM852x480[1];
84/*1024x512 (GTF)*/
85extern struct crt_mode_table CRTM1024x512[1];
86/* 1024x600*/
87extern struct crt_mode_table CRTM1024x600[1];
88/* 1024x768*/
89extern struct crt_mode_table CRTM1024x768[4];
90/* 1152x864*/
91extern struct crt_mode_table CRTM1152x864[1];
92/* 1280x720 (HDMI 720P)*/
93extern struct crt_mode_table CRTM1280x720[2];
94/*1280x768 (GTF)*/
95extern struct crt_mode_table CRTM1280x768[2];
96/* 1280x800 (CVT) */
97extern struct crt_mode_table CRTM1280x800[1];
98/*1280x960*/
99extern struct crt_mode_table CRTM1280x960[1];
100/* 1280x1024*/
101extern struct crt_mode_table CRTM1280x1024[3];
102/* 1368x768 (GTF) */
103extern struct crt_mode_table CRTM1368x768[1];
104/*1440x1050 (GTF)*/
105extern struct crt_mode_table CRTM1440x1050[1];
106/* 1600x1200*/
107extern struct crt_mode_table CRTM1600x1200[2];
108/* 1680x1050 (CVT) */
109extern struct crt_mode_table CRTM1680x1050[2];
110/* 1680x1050 (CVT Reduce Blanking) */
111extern struct crt_mode_table CRTM1680x1050_RB[1];
112/* 1920x1080 (CVT)*/
113extern struct crt_mode_table CRTM1920x1080[1];
114/* 1920x1080 (CVT with Reduce Blanking) */
115extern struct crt_mode_table CRTM1920x1080_RB[1];
116/* 1920x1440*/
117extern struct crt_mode_table CRTM1920x1440[2];
118/* 1400x1050 (CVT) */
119extern struct crt_mode_table CRTM1400x1050[2];
120/* 1400x1050 (CVT Reduce Blanking) */
121extern struct crt_mode_table CRTM1400x1050_RB[1];
122/* 960x600 (CVT) */
123extern struct crt_mode_table CRTM960x600[1];
124/* 1000x600 (GTF) */
125extern struct crt_mode_table CRTM1000x600[1];
126/* 1024x576 (GTF) */
127extern struct crt_mode_table CRTM1024x576[1];
128/* 1088x612 (CVT) */
129extern struct crt_mode_table CRTM1088x612[1];
130/* 1152x720 (CVT) */
131extern struct crt_mode_table CRTM1152x720[1];
132/* 1200x720 (GTF) */
133extern struct crt_mode_table CRTM1200x720[1];
134/* 1280x600 (GTF) */
135extern struct crt_mode_table CRTM1280x600[1];
136/* 1360x768 (CVT) */
137extern struct crt_mode_table CRTM1360x768[1];
138/* 1360x768 (CVT Reduce Blanking) */
139extern struct crt_mode_table CRTM1360x768_RB[1];
140/* 1366x768 (GTF) */
141extern struct crt_mode_table CRTM1366x768[2];
142/* 1440x900 (CVT) */
143extern struct crt_mode_table CRTM1440x900[2];
144/* 1440x900 (CVT Reduce Blanking) */
145extern struct crt_mode_table CRTM1440x900_RB[1];
146/* 1600x900 (CVT) */
147extern struct crt_mode_table CRTM1600x900[1];
148/* 1600x900 (CVT Reduce Blanking) */
149extern struct crt_mode_table CRTM1600x900_RB[1];
150/* 1600x1024 (GTF) */
151extern struct crt_mode_table CRTM1600x1024[1];
152/* 1792x1344 (DMT) */
153extern struct crt_mode_table CRTM1792x1344[1];
154/* 1856x1392 (DMT) */
155extern struct crt_mode_table CRTM1856x1392[1];
156/* 1920x1200 (CVT) */
157extern struct crt_mode_table CRTM1920x1200[1];
158/* 1920x1200 (CVT with Reduce Blanking) */
159extern struct crt_mode_table CRTM1920x1200_RB[1];
160/* 2048x1536 (CVT) */
161extern struct crt_mode_table CRTM2048x1536[1];
162extern struct VideoModeTable CLE266Modes[47];
163extern struct crt_mode_table CEAM1280x720[1];
164extern struct crt_mode_table CEAM1920x1080[1];
165extern struct VideoModeTable CEA_HDMI_Modes[2];
166 72
167extern struct res_map_refresh res_map_refresh_tbl[61]; 73extern struct res_map_refresh res_map_refresh_tbl[];
168extern struct io_reg CN400_ModeXregs[52]; 74extern struct io_reg CN400_ModeXregs[];
169extern struct io_reg CN700_ModeXregs[66]; 75extern struct io_reg CN700_ModeXregs[];
170extern struct io_reg KM400_ModeXregs[55]; 76extern struct io_reg KM400_ModeXregs[];
171extern struct io_reg CX700_ModeXregs[58]; 77extern struct io_reg CX700_ModeXregs[];
172extern struct io_reg VX800_ModeXregs[58]; 78extern struct io_reg VX800_ModeXregs[];
173extern struct io_reg CLE266_ModeXregs[32]; 79extern struct io_reg VX855_ModeXregs[];
174extern struct io_reg PM1024x768[2]; 80extern struct io_reg CLE266_ModeXregs[];
175extern struct patch_table res_patch_table[1]; 81extern struct io_reg PM1024x768[];
82extern struct patch_table res_patch_table[];
176extern struct VPITTable VPIT; 83extern struct VPITTable VPIT;
177#endif /* __VIAMODE_H__ */ 84#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
index 322a9f993550..a6b37494e79a 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/via/vt1636.c
@@ -27,7 +27,7 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
27{ 27{
28 u8 data; 28 u8 data;
29 29
30 viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; 30 viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
31 viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data); 31 viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data);
32 32
33 return data; 33 return data;
@@ -39,7 +39,7 @@ void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
39{ 39{
40 int index, data; 40 int index, data;
41 41
42 viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; 42 viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
43 43
44 index = io_data.Index; 44 index = io_data.Index;
45 data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info, 45 data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index d0674f1e3f10..2376f688ec8b 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info)
523 info->fix.ywrapstep = 0; 523 info->fix.ywrapstep = 0;
524 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; 524 info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
525 525
526 mutex_lock(&info->mm_lock);
526 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { 527 if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
527 par->extmem_active = 1; 528 par->extmem_active = 1;
528 info->fix.smem_len = par->mach->mem->size+1; 529 info->fix.smem_len = par->mach->mem->size+1;
@@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info)
530 par->extmem_active = 0; 531 par->extmem_active = 0;
531 info->fix.smem_len = MEM_INT_SIZE+1; 532 info->fix.smem_len = MEM_INT_SIZE+1;
532 } 533 }
534 mutex_unlock(&info->mm_lock);
533 535
534 w100fb_activate_var(par); 536 w100fb_activate_var(par);
535 } 537 }
@@ -746,8 +748,6 @@ int __init w100fb_probe(struct platform_device *pdev)
746 goto out; 748 goto out;
747 } 749 }
748 750
749 w100fb_set_par(info);
750
751 if (register_framebuffer(info) < 0) { 751 if (register_framebuffer(info) < 0) {
752 err = -EINVAL; 752 err = -EINVAL;
753 goto out; 753 goto out;
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 15502d5e3641..54cd91610174 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -454,6 +454,10 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
454 454
455 xenfb_init_shared_page(info, fb_info); 455 xenfb_init_shared_page(info, fb_info);
456 456
457 ret = xenfb_connect_backend(dev, info);
458 if (ret < 0)
459 goto error;
460
457 ret = register_framebuffer(fb_info); 461 ret = register_framebuffer(fb_info);
458 if (ret) { 462 if (ret) {
459 fb_deferred_io_cleanup(fb_info); 463 fb_deferred_io_cleanup(fb_info);
@@ -464,10 +468,6 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
464 } 468 }
465 info->fb_info = fb_info; 469 info->fb_info = fb_info;
466 470
467 ret = xenfb_connect_backend(dev, info);
468 if (ret < 0)
469 goto error;
470
471 xenfb_make_preferred_console(); 471 xenfb_make_preferred_console();
472 return 0; 472 return 0;
473 473