diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-03 13:28:46 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-03 13:28:46 -0400 |
commit | f68ec0c24755e5cdb779be6240925f2175311d84 (patch) | |
tree | a7b7128e61a8456385d82bd1c7ca5f14eecbf2ca /drivers/video | |
parent | 98920dc3d1113b883cbc73e3293446d3525c6042 (diff) | |
parent | 94aca1dac6f6d21f4b07e4864baf7768cabcc6e7 (diff) |
Merge commit 'v2.6.27-rc8' into x86/setup
Diffstat (limited to 'drivers/video')
110 files changed, 6232 insertions, 1560 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d58509a67068..3773d7d89243 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1656,6 +1656,32 @@ config FB_PM3 | |||
1656 | similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 | 1656 | similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 |
1657 | and maybe other boards. | 1657 | and maybe other boards. |
1658 | 1658 | ||
1659 | config FB_CARMINE | ||
1660 | tristate "Fujitsu carmine frame buffer support" | ||
1661 | depends on FB && PCI | ||
1662 | select FB_CFB_FILLRECT | ||
1663 | select FB_CFB_COPYAREA | ||
1664 | select FB_CFB_IMAGEBLIT | ||
1665 | help | ||
1666 | This is the frame buffer device driver for the Fujitsu Carmine chip. | ||
1667 | The driver provides two independent frame buffer devices. | ||
1668 | |||
1669 | choice | ||
1670 | depends on FB_CARMINE | ||
1671 | prompt "DRAM timing" | ||
1672 | default FB_CARMINE_DRAM_EVAL | ||
1673 | |||
1674 | config FB_CARMINE_DRAM_EVAL | ||
1675 | bool "Eval board timings" | ||
1676 | help | ||
1677 | Use timings which work on the eval card. | ||
1678 | |||
1679 | config CARMINE_DRAM_CUSTOM | ||
1680 | bool "Custom board timings" | ||
1681 | help | ||
1682 | Use custom board timings. | ||
1683 | endchoice | ||
1684 | |||
1659 | config FB_AU1100 | 1685 | config FB_AU1100 |
1660 | bool "Au1100 LCD Driver" | 1686 | bool "Au1100 LCD Driver" |
1661 | depends on (FB = y) && MIPS && SOC_AU1100 | 1687 | depends on (FB = y) && MIPS && SOC_AU1100 |
@@ -1838,6 +1864,16 @@ config FB_W100 | |||
1838 | 1864 | ||
1839 | If unsure, say N. | 1865 | If unsure, say N. |
1840 | 1866 | ||
1867 | config FB_SH_MOBILE_LCDC | ||
1868 | tristate "SuperH Mobile LCDC framebuffer support" | ||
1869 | depends on FB && SUPERH | ||
1870 | select FB_CFB_FILLRECT | ||
1871 | select FB_CFB_COPYAREA | ||
1872 | select FB_CFB_IMAGEBLIT | ||
1873 | default m | ||
1874 | ---help--- | ||
1875 | Frame buffer driver for the on-chip SH-Mobile LCD controller. | ||
1876 | |||
1841 | config FB_S3C2410 | 1877 | config FB_S3C2410 |
1842 | tristate "S3C2410 LCD framebuffer support" | 1878 | tristate "S3C2410 LCD framebuffer support" |
1843 | depends on FB && ARCH_S3C2410 | 1879 | depends on FB && ARCH_S3C2410 |
@@ -1949,6 +1985,23 @@ config FB_AM200EPD | |||
1949 | This enables support for the Metronome display controller used on | 1985 | This enables support for the Metronome display controller used on |
1950 | the E-Ink AM-200 EPD devkit. | 1986 | the E-Ink AM-200 EPD devkit. |
1951 | 1987 | ||
1988 | config FB_COBALT | ||
1989 | tristate "Cobalt server LCD frame buffer support" | ||
1990 | depends on FB && MIPS_COBALT | ||
1991 | |||
1992 | config FB_SH7760 | ||
1993 | bool "SH7760/SH7763 LCDC support" | ||
1994 | depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763) | ||
1995 | select FB_CFB_FILLRECT | ||
1996 | select FB_CFB_COPYAREA | ||
1997 | select FB_CFB_IMAGEBLIT | ||
1998 | help | ||
1999 | Support for the SH7760/SH7763 integrated (D)STN/TFT LCD Controller. | ||
2000 | Supports display resolutions up to 1024x1024 pixel, grayscale and | ||
2001 | color operation, with depths ranging from 1 bpp to 8 bpp monochrome | ||
2002 | and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for | ||
2003 | panels <= 320 pixel horizontal resolution. | ||
2004 | |||
1952 | config FB_VIRTUAL | 2005 | config FB_VIRTUAL |
1953 | tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" | 2006 | tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" |
1954 | depends on FB | 2007 | depends on FB |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 04bca35403ff..a6b55297a7fb 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -106,17 +106,21 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o | |||
106 | obj-$(CONFIG_FB_MAXINE) += maxinefb.o | 106 | obj-$(CONFIG_FB_MAXINE) += maxinefb.o |
107 | obj-$(CONFIG_FB_METRONOME) += metronomefb.o | 107 | obj-$(CONFIG_FB_METRONOME) += metronomefb.o |
108 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o | 108 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o |
109 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o | ||
109 | obj-$(CONFIG_FB_IMX) += imxfb.o | 110 | obj-$(CONFIG_FB_IMX) += imxfb.o |
110 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o | 111 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o |
111 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o | 112 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o |
113 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o | ||
112 | obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ | 114 | obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ |
113 | obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ | 115 | obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ |
114 | obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | 116 | obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o |
115 | obj-$(CONFIG_FB_PS3) += ps3fb.o | 117 | obj-$(CONFIG_FB_PS3) += ps3fb.o |
116 | obj-$(CONFIG_FB_SM501) += sm501fb.o | 118 | obj-$(CONFIG_FB_SM501) += sm501fb.o |
117 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o | 119 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o |
120 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o | ||
118 | obj-$(CONFIG_FB_OMAP) += omap/ | 121 | obj-$(CONFIG_FB_OMAP) += omap/ |
119 | obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o | 122 | obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o |
123 | obj-$(CONFIG_FB_CARMINE) += carminefb.o | ||
120 | 124 | ||
121 | # Platform or fallback drivers go here | 125 | # Platform or fallback drivers go here |
122 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | 126 | obj-$(CONFIG_FB_UVESA) += uvesafb.o |
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index eedb8285e32f..61c3d3f40fd1 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c | |||
@@ -23,12 +23,13 @@ | |||
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/ctype.h> | 24 | #include <linux/ctype.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/mm.h> | ||
26 | #include <linux/init.h> | 27 | #include <linux/init.h> |
27 | #include <linux/fb.h> | 28 | #include <linux/fb.h> |
28 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
29 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> |
30 | 31 | ||
31 | #include <asm/hardware.h> | 32 | #include <mach/hardware.h> |
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
33 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
34 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
@@ -338,7 +339,7 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
338 | #endif | 339 | #endif |
339 | 340 | ||
340 | #ifdef HAS_VIDC20 | 341 | #ifdef HAS_VIDC20 |
341 | #include <asm/arch/acornfb.h> | 342 | #include <mach/acornfb.h> |
342 | 343 | ||
343 | #define MAX_SIZE 2*1024*1024 | 344 | #define MAX_SIZE 2*1024*1024 |
344 | 345 | ||
diff --git a/drivers/video/am200epd.c b/drivers/video/am200epd.c index 51e26c1f5e8b..0c35b8b0160e 100644 --- a/drivers/video/am200epd.c +++ b/drivers/video/am200epd.c | |||
@@ -33,7 +33,7 @@ | |||
33 | 33 | ||
34 | #include <video/metronomefb.h> | 34 | #include <video/metronomefb.h> |
35 | 35 | ||
36 | #include <asm/arch/pxa-regs.h> | 36 | #include <mach/pxa-regs.h> |
37 | 37 | ||
38 | /* register offsets for gpio control */ | 38 | /* register offsets for gpio control */ |
39 | #define LED_GPIO_PIN 51 | 39 | #define LED_GPIO_PIN 51 |
@@ -221,7 +221,7 @@ static int am200_setup_irq(struct fb_info *info) | |||
221 | return retval; | 221 | return retval; |
222 | } | 222 | } |
223 | 223 | ||
224 | return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING); | 224 | return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQ_TYPE_EDGE_FALLING); |
225 | } | 225 | } |
226 | 226 | ||
227 | static void am200_set_rst(struct metronomefb_par *par, int state) | 227 | static void am200_set_rst(struct metronomefb_par *par, int state) |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 05a328c11a8b..b8e9a8682f2d 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
@@ -1136,7 +1136,6 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg | |||
1136 | * Interface to the low level console driver | 1136 | * Interface to the low level console driver |
1137 | */ | 1137 | */ |
1138 | 1138 | ||
1139 | int amifb_init(void); | ||
1140 | static void amifb_deinit(void); | 1139 | static void amifb_deinit(void); |
1141 | 1140 | ||
1142 | /* | 1141 | /* |
@@ -2048,13 +2047,16 @@ static void amifb_copyarea(struct fb_info *info, | |||
2048 | width = x2 - dx; | 2047 | width = x2 - dx; |
2049 | height = y2 - dy; | 2048 | height = y2 - dy; |
2050 | 2049 | ||
2050 | if (area->sx + dx < area->dx || area->sy + dy < area->dy) | ||
2051 | return; | ||
2052 | |||
2051 | /* update sx,sy */ | 2053 | /* update sx,sy */ |
2052 | sx = area->sx + (dx - area->dx); | 2054 | sx = area->sx + (dx - area->dx); |
2053 | sy = area->sy + (dy - area->dy); | 2055 | sy = area->sy + (dy - area->dy); |
2054 | 2056 | ||
2055 | /* the source must be completely inside the virtual screen */ | 2057 | /* the source must be completely inside the virtual screen */ |
2056 | if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || | 2058 | if (sx + width > info->var.xres_virtual || |
2057 | (sy + height) > info->var.yres_virtual) | 2059 | sy + height > info->var.yres_virtual) |
2058 | return; | 2060 | return; |
2059 | 2061 | ||
2060 | if (dy > sy || (dy == sy && dx > sx)) { | 2062 | if (dy > sy || (dy == sy && dx > sx)) { |
@@ -2245,7 +2247,7 @@ static inline void chipfree(void) | |||
2245 | * Initialisation | 2247 | * Initialisation |
2246 | */ | 2248 | */ |
2247 | 2249 | ||
2248 | int __init amifb_init(void) | 2250 | static int __init amifb_init(void) |
2249 | { | 2251 | { |
2250 | int tag, i, err = 0; | 2252 | int tag, i, err = 0; |
2251 | u_long chipptr; | 2253 | u_long chipptr; |
@@ -2383,6 +2385,9 @@ default_chipset: | |||
2383 | goto amifb_error; | 2385 | goto amifb_error; |
2384 | } | 2386 | } |
2385 | 2387 | ||
2388 | fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, | ||
2389 | &fb_info.modelist); | ||
2390 | |||
2386 | round_down_bpp = 0; | 2391 | round_down_bpp = 0; |
2387 | chipptr = chipalloc(fb_info.fix.smem_len+ | 2392 | chipptr = chipalloc(fb_info.fix.smem_len+ |
2388 | SPRITEMEMSIZE+ | 2393 | SPRITEMEMSIZE+ |
@@ -3787,16 +3792,14 @@ static void ami_rebuild_copper(void) | |||
3787 | } | 3792 | } |
3788 | } | 3793 | } |
3789 | 3794 | ||
3790 | 3795 | static void __exit amifb_exit(void) | |
3791 | module_init(amifb_init); | ||
3792 | |||
3793 | #ifdef MODULE | ||
3794 | MODULE_LICENSE("GPL"); | ||
3795 | |||
3796 | void cleanup_module(void) | ||
3797 | { | 3796 | { |
3798 | unregister_framebuffer(&fb_info); | 3797 | unregister_framebuffer(&fb_info); |
3799 | amifb_deinit(); | 3798 | amifb_deinit(); |
3800 | amifb_video_off(); | 3799 | amifb_video_off(); |
3801 | } | 3800 | } |
3802 | #endif /* MODULE */ | 3801 | |
3802 | module_init(amifb_init); | ||
3803 | module_exit(amifb_exit); | ||
3804 | |||
3805 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 5001bd4ef466..314d18694b6a 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * Code is based on s3fb | 11 | * Code is based on s3fb |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/version.h> | ||
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
@@ -958,20 +957,20 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_ | |||
958 | /* Prepare PCI device */ | 957 | /* Prepare PCI device */ |
959 | rc = pci_enable_device(dev); | 958 | rc = pci_enable_device(dev); |
960 | if (rc < 0) { | 959 | if (rc < 0) { |
961 | dev_err(info->dev, "cannot enable PCI device\n"); | 960 | dev_err(info->device, "cannot enable PCI device\n"); |
962 | goto err_enable_device; | 961 | goto err_enable_device; |
963 | } | 962 | } |
964 | 963 | ||
965 | rc = pci_request_regions(dev, "arkfb"); | 964 | rc = pci_request_regions(dev, "arkfb"); |
966 | if (rc < 0) { | 965 | if (rc < 0) { |
967 | dev_err(info->dev, "cannot reserve framebuffer region\n"); | 966 | dev_err(info->device, "cannot reserve framebuffer region\n"); |
968 | goto err_request_regions; | 967 | goto err_request_regions; |
969 | } | 968 | } |
970 | 969 | ||
971 | par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info); | 970 | par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info); |
972 | if (! par->dac) { | 971 | if (! par->dac) { |
973 | rc = -ENOMEM; | 972 | rc = -ENOMEM; |
974 | dev_err(info->dev, "RAMDAC initialization failed\n"); | 973 | dev_err(info->device, "RAMDAC initialization failed\n"); |
975 | goto err_dac; | 974 | goto err_dac; |
976 | } | 975 | } |
977 | 976 | ||
@@ -982,7 +981,7 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_ | |||
982 | info->screen_base = pci_iomap(dev, 0, 0); | 981 | info->screen_base = pci_iomap(dev, 0, 0); |
983 | if (! info->screen_base) { | 982 | if (! info->screen_base) { |
984 | rc = -ENOMEM; | 983 | rc = -ENOMEM; |
985 | dev_err(info->dev, "iomap for framebuffer failed\n"); | 984 | dev_err(info->device, "iomap for framebuffer failed\n"); |
986 | goto err_iomap; | 985 | goto err_iomap; |
987 | } | 986 | } |
988 | 987 | ||
@@ -1004,19 +1003,19 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_ | |||
1004 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 1003 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); |
1005 | if (! ((rc == 1) || (rc == 2))) { | 1004 | if (! ((rc == 1) || (rc == 2))) { |
1006 | rc = -EINVAL; | 1005 | rc = -EINVAL; |
1007 | dev_err(info->dev, "mode %s not found\n", mode_option); | 1006 | dev_err(info->device, "mode %s not found\n", mode_option); |
1008 | goto err_find_mode; | 1007 | goto err_find_mode; |
1009 | } | 1008 | } |
1010 | 1009 | ||
1011 | rc = fb_alloc_cmap(&info->cmap, 256, 0); | 1010 | rc = fb_alloc_cmap(&info->cmap, 256, 0); |
1012 | if (rc < 0) { | 1011 | if (rc < 0) { |
1013 | dev_err(info->dev, "cannot allocate colormap\n"); | 1012 | dev_err(info->device, "cannot allocate colormap\n"); |
1014 | goto err_alloc_cmap; | 1013 | goto err_alloc_cmap; |
1015 | } | 1014 | } |
1016 | 1015 | ||
1017 | rc = register_framebuffer(info); | 1016 | rc = register_framebuffer(info); |
1018 | if (rc < 0) { | 1017 | if (rc < 0) { |
1019 | dev_err(info->dev, "cannot register framebugger\n"); | 1018 | dev_err(info->device, "cannot register framebugger\n"); |
1020 | goto err_reg_fb; | 1019 | goto err_reg_fb; |
1021 | } | 1020 | } |
1022 | 1021 | ||
@@ -1090,7 +1089,7 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state) | |||
1090 | struct fb_info *info = pci_get_drvdata(dev); | 1089 | struct fb_info *info = pci_get_drvdata(dev); |
1091 | struct arkfb_info *par = info->par; | 1090 | struct arkfb_info *par = info->par; |
1092 | 1091 | ||
1093 | dev_info(info->dev, "suspend\n"); | 1092 | dev_info(info->device, "suspend\n"); |
1094 | 1093 | ||
1095 | acquire_console_sem(); | 1094 | acquire_console_sem(); |
1096 | mutex_lock(&(par->open_lock)); | 1095 | mutex_lock(&(par->open_lock)); |
@@ -1121,16 +1120,13 @@ static int ark_pci_resume (struct pci_dev* dev) | |||
1121 | struct fb_info *info = pci_get_drvdata(dev); | 1120 | struct fb_info *info = pci_get_drvdata(dev); |
1122 | struct arkfb_info *par = info->par; | 1121 | struct arkfb_info *par = info->par; |
1123 | 1122 | ||
1124 | dev_info(info->dev, "resume\n"); | 1123 | dev_info(info->device, "resume\n"); |
1125 | 1124 | ||
1126 | acquire_console_sem(); | 1125 | acquire_console_sem(); |
1127 | mutex_lock(&(par->open_lock)); | 1126 | mutex_lock(&(par->open_lock)); |
1128 | 1127 | ||
1129 | if (par->ref_count == 0) { | 1128 | if (par->ref_count == 0) |
1130 | mutex_unlock(&(par->open_lock)); | 1129 | goto fail; |
1131 | release_console_sem(); | ||
1132 | return 0; | ||
1133 | } | ||
1134 | 1130 | ||
1135 | pci_set_power_state(dev, PCI_D0); | 1131 | pci_set_power_state(dev, PCI_D0); |
1136 | pci_restore_state(dev); | 1132 | pci_restore_state(dev); |
@@ -1143,8 +1139,8 @@ static int ark_pci_resume (struct pci_dev* dev) | |||
1143 | arkfb_set_par(info); | 1139 | arkfb_set_par(info); |
1144 | fb_set_suspend(info, 0); | 1140 | fb_set_suspend(info, 0); |
1145 | 1141 | ||
1146 | mutex_unlock(&(par->open_lock)); | ||
1147 | fail: | 1142 | fail: |
1143 | mutex_unlock(&(par->open_lock)); | ||
1148 | release_console_sem(); | 1144 | release_console_sem(); |
1149 | return 0; | 1145 | return 0; |
1150 | } | 1146 | } |
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index dff35474b854..77eb8b34fbfa 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
@@ -2593,13 +2593,16 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | |||
2593 | width = x2 - dx; | 2593 | width = x2 - dx; |
2594 | height = y2 - dy; | 2594 | height = y2 - dy; |
2595 | 2595 | ||
2596 | if (area->sx + dx < area->dx || area->sy + dy < area->dy) | ||
2597 | return; | ||
2598 | |||
2596 | /* update sx,sy */ | 2599 | /* update sx,sy */ |
2597 | sx = area->sx + (dx - area->dx); | 2600 | sx = area->sx + (dx - area->dx); |
2598 | sy = area->sy + (dy - area->dy); | 2601 | sy = area->sy + (dy - area->dy); |
2599 | 2602 | ||
2600 | /* the source must be completely inside the virtual screen */ | 2603 | /* the source must be completely inside the virtual screen */ |
2601 | if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || | 2604 | if (sx + width > info->var.xres_virtual || |
2602 | (sy + height) > info->var.yres_virtual) | 2605 | sy + height > info->var.yres_virtual) |
2603 | return; | 2606 | return; |
2604 | 2607 | ||
2605 | if (dy > sy || (dy == sy && dx > sx)) { | 2608 | if (dy > sy || (dy == sy && dx > sx)) { |
@@ -3110,7 +3113,7 @@ int __init atafb_init(void) | |||
3110 | printk("atafb_init: start\n"); | 3113 | printk("atafb_init: start\n"); |
3111 | 3114 | ||
3112 | if (!MACH_IS_ATARI) | 3115 | if (!MACH_IS_ATARI) |
3113 | return -ENXIO; | 3116 | return -ENODEV; |
3114 | 3117 | ||
3115 | do { | 3118 | do { |
3116 | #ifdef ATAFB_EXT | 3119 | #ifdef ATAFB_EXT |
@@ -3230,6 +3233,9 @@ int __init atafb_init(void) | |||
3230 | return -EINVAL; | 3233 | return -EINVAL; |
3231 | } | 3234 | } |
3232 | 3235 | ||
3236 | fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES, | ||
3237 | &fb_info.modelist); | ||
3238 | |||
3233 | atafb_set_disp(&fb_info); | 3239 | atafb_set_disp(&fb_info); |
3234 | 3240 | ||
3235 | fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0); | 3241 | fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0); |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index b004036d4087..75dac578104f 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/backlight.h> | 19 | #include <linux/backlight.h> |
20 | 20 | ||
21 | #include <asm/arch/board.h> | 21 | #include <mach/board.h> |
22 | #include <asm/arch/cpu.h> | 22 | #include <mach/cpu.h> |
23 | #include <asm/arch/gpio.h> | 23 | #include <mach/gpio.h> |
24 | 24 | ||
25 | #include <video/atmel_lcdc.h> | 25 | #include <video/atmel_lcdc.h> |
26 | 26 | ||
@@ -39,7 +39,9 @@ | |||
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #if defined(CONFIG_ARCH_AT91) | 41 | #if defined(CONFIG_ARCH_AT91) |
42 | #define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT | 42 | #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ |
43 | | FBINFO_PARTIAL_PAN_OK \ | ||
44 | | FBINFO_HWACCEL_YPAN) | ||
43 | 45 | ||
44 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | 46 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
45 | struct fb_var_screeninfo *var) | 47 | struct fb_var_screeninfo *var) |
@@ -177,7 +179,7 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | |||
177 | .type = FB_TYPE_PACKED_PIXELS, | 179 | .type = FB_TYPE_PACKED_PIXELS, |
178 | .visual = FB_VISUAL_TRUECOLOR, | 180 | .visual = FB_VISUAL_TRUECOLOR, |
179 | .xpanstep = 0, | 181 | .xpanstep = 0, |
180 | .ypanstep = 0, | 182 | .ypanstep = 1, |
181 | .ywrapstep = 0, | 183 | .ywrapstep = 0, |
182 | .accel = FB_ACCEL_NONE, | 184 | .accel = FB_ACCEL_NONE, |
183 | }; | 185 | }; |
@@ -206,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) | |||
206 | return value; | 208 | return value; |
207 | } | 209 | } |
208 | 210 | ||
211 | static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo) | ||
212 | { | ||
213 | /* Turn off the LCD controller and the DMA controller */ | ||
214 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
215 | sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); | ||
216 | |||
217 | /* Wait for the LCDC core to become idle */ | ||
218 | while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) | ||
219 | msleep(10); | ||
220 | |||
221 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | ||
222 | } | ||
223 | |||
224 | static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo) | ||
225 | { | ||
226 | atmel_lcdfb_stop_nowait(sinfo); | ||
227 | |||
228 | /* Wait for DMA engine to become idle... */ | ||
229 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | ||
230 | msleep(10); | ||
231 | } | ||
232 | |||
233 | static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo) | ||
234 | { | ||
235 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); | ||
236 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
237 | (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ||
238 | | ATMEL_LCDC_PWR); | ||
239 | } | ||
240 | |||
209 | static void atmel_lcdfb_update_dma(struct fb_info *info, | 241 | static void atmel_lcdfb_update_dma(struct fb_info *info, |
210 | struct fb_var_screeninfo *var) | 242 | struct fb_var_screeninfo *var) |
211 | { | 243 | { |
@@ -240,9 +272,11 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | |||
240 | { | 272 | { |
241 | struct fb_info *info = sinfo->info; | 273 | struct fb_info *info = sinfo->info; |
242 | struct fb_var_screeninfo *var = &info->var; | 274 | struct fb_var_screeninfo *var = &info->var; |
275 | unsigned int smem_len; | ||
243 | 276 | ||
244 | info->fix.smem_len = (var->xres_virtual * var->yres_virtual | 277 | smem_len = (var->xres_virtual * var->yres_virtual |
245 | * ((var->bits_per_pixel + 7) / 8)); | 278 | * ((var->bits_per_pixel + 7) / 8)); |
279 | info->fix.smem_len = max(smem_len, sinfo->smem_len); | ||
246 | 280 | ||
247 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, | 281 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, |
248 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); | 282 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); |
@@ -256,6 +290,20 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | |||
256 | return 0; | 290 | return 0; |
257 | } | 291 | } |
258 | 292 | ||
293 | static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var, | ||
294 | struct fb_info *info) | ||
295 | { | ||
296 | struct fb_videomode varfbmode; | ||
297 | const struct fb_videomode *fbmode = NULL; | ||
298 | |||
299 | fb_var_to_videomode(&varfbmode, var); | ||
300 | fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist); | ||
301 | if (fbmode) | ||
302 | fb_videomode_to_var(var, fbmode); | ||
303 | return fbmode; | ||
304 | } | ||
305 | |||
306 | |||
259 | /** | 307 | /** |
260 | * atmel_lcdfb_check_var - Validates a var passed in. | 308 | * atmel_lcdfb_check_var - Validates a var passed in. |
261 | * @var: frame buffer variable screen structure | 309 | * @var: frame buffer variable screen structure |
@@ -289,6 +337,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
289 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; | 337 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; |
290 | 338 | ||
291 | dev_dbg(dev, "%s:\n", __func__); | 339 | dev_dbg(dev, "%s:\n", __func__); |
340 | |||
341 | if (!(var->pixclock && var->bits_per_pixel)) { | ||
342 | /* choose a suitable mode if possible */ | ||
343 | if (!atmel_lcdfb_choose_mode(var, info)) { | ||
344 | dev_err(dev, "needed value not specified\n"); | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | } | ||
348 | |||
292 | dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); | 349 | dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); |
293 | dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); | 350 | dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); |
294 | dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); | 351 | dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); |
@@ -299,6 +356,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
299 | return -EINVAL; | 356 | return -EINVAL; |
300 | } | 357 | } |
301 | 358 | ||
359 | /* Do not allow to have real resoulution larger than virtual */ | ||
360 | if (var->xres > var->xres_virtual) | ||
361 | var->xres_virtual = var->xres; | ||
362 | |||
363 | if (var->yres > var->yres_virtual) | ||
364 | var->yres_virtual = var->yres; | ||
365 | |||
302 | /* Force same alignment for each line */ | 366 | /* Force same alignment for each line */ |
303 | var->xres = (var->xres + 3) & ~3UL; | 367 | var->xres = (var->xres + 3) & ~3UL; |
304 | var->xres_virtual = (var->xres_virtual + 3) & ~3UL; | 368 | var->xres_virtual = (var->xres_virtual + 3) & ~3UL; |
@@ -379,6 +443,17 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
379 | return 0; | 443 | return 0; |
380 | } | 444 | } |
381 | 445 | ||
446 | /* | ||
447 | * LCD reset sequence | ||
448 | */ | ||
449 | static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo) | ||
450 | { | ||
451 | might_sleep(); | ||
452 | |||
453 | atmel_lcdfb_stop(sinfo); | ||
454 | atmel_lcdfb_start(sinfo); | ||
455 | } | ||
456 | |||
382 | /** | 457 | /** |
383 | * atmel_lcdfb_set_par - Alters the hardware state. | 458 | * atmel_lcdfb_set_par - Alters the hardware state. |
384 | * @info: frame buffer structure that represents a single frame buffer | 459 | * @info: frame buffer structure that represents a single frame buffer |
@@ -401,19 +476,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
401 | unsigned long clk_value_khz; | 476 | unsigned long clk_value_khz; |
402 | unsigned long bits_per_line; | 477 | unsigned long bits_per_line; |
403 | 478 | ||
479 | might_sleep(); | ||
480 | |||
404 | dev_dbg(info->device, "%s:\n", __func__); | 481 | dev_dbg(info->device, "%s:\n", __func__); |
405 | dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", | 482 | dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", |
406 | info->var.xres, info->var.yres, | 483 | info->var.xres, info->var.yres, |
407 | info->var.xres_virtual, info->var.yres_virtual); | 484 | info->var.xres_virtual, info->var.yres_virtual); |
408 | 485 | ||
409 | /* Turn off the LCD controller and the DMA controller */ | 486 | atmel_lcdfb_stop_nowait(sinfo); |
410 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); | ||
411 | |||
412 | /* Wait for the LCDC core to become idle */ | ||
413 | while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) | ||
414 | msleep(10); | ||
415 | |||
416 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); | ||
417 | 487 | ||
418 | if (info->var.bits_per_pixel == 1) | 488 | if (info->var.bits_per_pixel == 1) |
419 | info->fix.visual = FB_VISUAL_MONO01; | 489 | info->fix.visual = FB_VISUAL_MONO01; |
@@ -511,18 +581,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
511 | 581 | ||
512 | /* Disable all interrupts */ | 582 | /* Disable all interrupts */ |
513 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 583 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
584 | /* Enable FIFO & DMA errors */ | ||
585 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); | ||
514 | 586 | ||
515 | /* ...wait for DMA engine to become idle... */ | 587 | /* ...wait for DMA engine to become idle... */ |
516 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | 588 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) |
517 | msleep(10); | 589 | msleep(10); |
518 | 590 | ||
519 | dev_dbg(info->device, " * re-enable DMA engine\n"); | 591 | atmel_lcdfb_start(sinfo); |
520 | /* ...and enable it with updated configuration */ | ||
521 | lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon); | ||
522 | |||
523 | dev_dbg(info->device, " * re-enable LCDC core\n"); | ||
524 | lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, | ||
525 | (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR); | ||
526 | 592 | ||
527 | dev_dbg(info->device, " * DONE\n"); | 593 | dev_dbg(info->device, " * DONE\n"); |
528 | 594 | ||
@@ -645,10 +711,26 @@ static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id) | |||
645 | u32 status; | 711 | u32 status; |
646 | 712 | ||
647 | status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); | 713 | status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); |
648 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, status); | 714 | if (status & ATMEL_LCDC_UFLWI) { |
715 | dev_warn(info->device, "FIFO underflow %#x\n", status); | ||
716 | /* reset DMA and FIFO to avoid screen shifting */ | ||
717 | schedule_work(&sinfo->task); | ||
718 | } | ||
719 | lcdc_writel(sinfo, ATMEL_LCDC_ICR, status); | ||
649 | return IRQ_HANDLED; | 720 | return IRQ_HANDLED; |
650 | } | 721 | } |
651 | 722 | ||
723 | /* | ||
724 | * LCD controller task (to reset the LCD) | ||
725 | */ | ||
726 | static void atmel_lcdfb_task(struct work_struct *work) | ||
727 | { | ||
728 | struct atmel_lcdfb_info *sinfo = | ||
729 | container_of(work, struct atmel_lcdfb_info, task); | ||
730 | |||
731 | atmel_lcdfb_reset(sinfo); | ||
732 | } | ||
733 | |||
652 | static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) | 734 | static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) |
653 | { | 735 | { |
654 | struct fb_info *info = sinfo->info; | 736 | struct fb_info *info = sinfo->info; |
@@ -691,6 +773,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
691 | struct fb_info *info; | 773 | struct fb_info *info; |
692 | struct atmel_lcdfb_info *sinfo; | 774 | struct atmel_lcdfb_info *sinfo; |
693 | struct atmel_lcdfb_info *pdata_sinfo; | 775 | struct atmel_lcdfb_info *pdata_sinfo; |
776 | struct fb_videomode fbmode; | ||
694 | struct resource *regs = NULL; | 777 | struct resource *regs = NULL; |
695 | struct resource *map = NULL; | 778 | struct resource *map = NULL; |
696 | int ret; | 779 | int ret; |
@@ -714,6 +797,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
714 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; | 797 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; |
715 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; | 798 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; |
716 | sinfo->guard_time = pdata_sinfo->guard_time; | 799 | sinfo->guard_time = pdata_sinfo->guard_time; |
800 | sinfo->smem_len = pdata_sinfo->smem_len; | ||
717 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; | 801 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; |
718 | sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; | 802 | sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; |
719 | } else { | 803 | } else { |
@@ -824,6 +908,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
824 | goto unmap_mmio; | 908 | goto unmap_mmio; |
825 | } | 909 | } |
826 | 910 | ||
911 | /* Some operations on the LCDC might sleep and | ||
912 | * require a preemptible task context */ | ||
913 | INIT_WORK(&sinfo->task, atmel_lcdfb_task); | ||
914 | |||
827 | ret = atmel_lcdfb_init_fbinfo(sinfo); | 915 | ret = atmel_lcdfb_init_fbinfo(sinfo); |
828 | if (ret < 0) { | 916 | if (ret < 0) { |
829 | dev_err(dev, "init fbinfo failed: %d\n", ret); | 917 | dev_err(dev, "init fbinfo failed: %d\n", ret); |
@@ -850,9 +938,13 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
850 | ret = register_framebuffer(info); | 938 | ret = register_framebuffer(info); |
851 | if (ret < 0) { | 939 | if (ret < 0) { |
852 | dev_err(dev, "failed to register framebuffer device: %d\n", ret); | 940 | dev_err(dev, "failed to register framebuffer device: %d\n", ret); |
853 | goto free_cmap; | 941 | goto reset_drvdata; |
854 | } | 942 | } |
855 | 943 | ||
944 | /* add selected videomode to modelist */ | ||
945 | fb_var_to_videomode(&fbmode, &info->var); | ||
946 | fb_add_videomode(&fbmode, &info->modelist); | ||
947 | |||
856 | /* Power up the LCDC screen */ | 948 | /* Power up the LCDC screen */ |
857 | if (sinfo->atmel_lcdfb_power_control) | 949 | if (sinfo->atmel_lcdfb_power_control) |
858 | sinfo->atmel_lcdfb_power_control(1); | 950 | sinfo->atmel_lcdfb_power_control(1); |
@@ -862,10 +954,12 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
862 | 954 | ||
863 | return 0; | 955 | return 0; |
864 | 956 | ||
865 | 957 | reset_drvdata: | |
958 | dev_set_drvdata(dev, NULL); | ||
866 | free_cmap: | 959 | free_cmap: |
867 | fb_dealloc_cmap(&info->cmap); | 960 | fb_dealloc_cmap(&info->cmap); |
868 | unregister_irqs: | 961 | unregister_irqs: |
962 | cancel_work_sync(&sinfo->task); | ||
869 | free_irq(sinfo->irq_base, info); | 963 | free_irq(sinfo->irq_base, info); |
870 | unmap_mmio: | 964 | unmap_mmio: |
871 | exit_backlight(sinfo); | 965 | exit_backlight(sinfo); |
@@ -898,11 +992,13 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
898 | { | 992 | { |
899 | struct device *dev = &pdev->dev; | 993 | struct device *dev = &pdev->dev; |
900 | struct fb_info *info = dev_get_drvdata(dev); | 994 | struct fb_info *info = dev_get_drvdata(dev); |
901 | struct atmel_lcdfb_info *sinfo = info->par; | 995 | struct atmel_lcdfb_info *sinfo; |
902 | 996 | ||
903 | if (!sinfo) | 997 | if (!info || !info->par) |
904 | return 0; | 998 | return 0; |
999 | sinfo = info->par; | ||
905 | 1000 | ||
1001 | cancel_work_sync(&sinfo->task); | ||
906 | exit_backlight(sinfo); | 1002 | exit_backlight(sinfo); |
907 | if (sinfo->atmel_lcdfb_power_control) | 1003 | if (sinfo->atmel_lcdfb_power_control) |
908 | sinfo->atmel_lcdfb_power_control(0); | 1004 | sinfo->atmel_lcdfb_power_control(0); |
@@ -935,11 +1031,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
935 | struct fb_info *info = platform_get_drvdata(pdev); | 1031 | struct fb_info *info = platform_get_drvdata(pdev); |
936 | struct atmel_lcdfb_info *sinfo = info->par; | 1032 | struct atmel_lcdfb_info *sinfo = info->par; |
937 | 1033 | ||
1034 | /* | ||
1035 | * We don't want to handle interrupts while the clock is | ||
1036 | * stopped. It may take forever. | ||
1037 | */ | ||
1038 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | ||
1039 | |||
938 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | 1040 | sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); |
939 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); | 1041 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); |
940 | if (sinfo->atmel_lcdfb_power_control) | 1042 | if (sinfo->atmel_lcdfb_power_control) |
941 | sinfo->atmel_lcdfb_power_control(0); | 1043 | sinfo->atmel_lcdfb_power_control(0); |
1044 | |||
1045 | atmel_lcdfb_stop(sinfo); | ||
942 | atmel_lcdfb_stop_clock(sinfo); | 1046 | atmel_lcdfb_stop_clock(sinfo); |
1047 | |||
943 | return 0; | 1048 | return 0; |
944 | } | 1049 | } |
945 | 1050 | ||
@@ -949,9 +1054,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev) | |||
949 | struct atmel_lcdfb_info *sinfo = info->par; | 1054 | struct atmel_lcdfb_info *sinfo = info->par; |
950 | 1055 | ||
951 | atmel_lcdfb_start_clock(sinfo); | 1056 | atmel_lcdfb_start_clock(sinfo); |
1057 | atmel_lcdfb_start(sinfo); | ||
952 | if (sinfo->atmel_lcdfb_power_control) | 1058 | if (sinfo->atmel_lcdfb_power_control) |
953 | sinfo->atmel_lcdfb_power_control(1); | 1059 | sinfo->atmel_lcdfb_power_control(1); |
954 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); | 1060 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); |
1061 | |||
1062 | /* Enable FIFO & DMA errors */ | ||
1063 | lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ||
1064 | | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI); | ||
1065 | |||
955 | return 0; | 1066 | return 0; |
956 | } | 1067 | } |
957 | 1068 | ||
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 24ee96c4e9e9..243ea4ab20c8 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -1339,10 +1339,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, | |||
1339 | if (vclk * 12 < c.ppll_min) | 1339 | if (vclk * 12 < c.ppll_min) |
1340 | vclk = c.ppll_min/12; | 1340 | vclk = c.ppll_min/12; |
1341 | 1341 | ||
1342 | pll->post_divider = -1; | ||
1343 | |||
1344 | /* now, find an acceptable divider */ | 1342 | /* now, find an acceptable divider */ |
1345 | for (i = 0; i < sizeof(post_dividers); i++) { | 1343 | for (i = 0; i < ARRAY_SIZE(post_dividers); i++) { |
1346 | output_freq = post_dividers[i] * vclk; | 1344 | output_freq = post_dividers[i] * vclk; |
1347 | if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) { | 1345 | if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) { |
1348 | pll->post_divider = post_dividers[i]; | 1346 | pll->post_divider = post_dividers[i]; |
@@ -1350,7 +1348,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, | |||
1350 | } | 1348 | } |
1351 | } | 1349 | } |
1352 | 1350 | ||
1353 | if (pll->post_divider < 0) | 1351 | if (i == ARRAY_SIZE(post_dividers)) |
1354 | return -EINVAL; | 1352 | return -EINVAL; |
1355 | 1353 | ||
1356 | /* calculate feedback divider */ | 1354 | /* calculate feedback divider */ |
@@ -1872,7 +1870,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i | |||
1872 | struct fb_info *info = pci_get_drvdata(pdev); | 1870 | struct fb_info *info = pci_get_drvdata(pdev); |
1873 | struct aty128fb_par *par = info->par; | 1871 | struct aty128fb_par *par = info->par; |
1874 | struct fb_var_screeninfo var; | 1872 | struct fb_var_screeninfo var; |
1875 | char video_card[DEVICE_NAME_SIZE]; | 1873 | char video_card[50]; |
1876 | u8 chip_rev; | 1874 | u8 chip_rev; |
1877 | u32 dac; | 1875 | u32 dac; |
1878 | 1876 | ||
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index bd4ac0bafecb..cc6b470073da 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
@@ -244,7 +244,7 @@ static int atyfb_sync(struct fb_info *info); | |||
244 | */ | 244 | */ |
245 | 245 | ||
246 | static int aty_init(struct fb_info *info); | 246 | static int aty_init(struct fb_info *info); |
247 | static void aty_resume_chip(struct fb_info *info); | 247 | |
248 | #ifdef CONFIG_ATARI | 248 | #ifdef CONFIG_ATARI |
249 | static int store_video_par(char *videopar, unsigned char m64_num); | 249 | static int store_video_par(char *videopar, unsigned char m64_num); |
250 | #endif | 250 | #endif |
@@ -424,7 +424,6 @@ static struct { | |||
424 | #endif /* CONFIG_FB_ATY_CT */ | 424 | #endif /* CONFIG_FB_ATY_CT */ |
425 | }; | 425 | }; |
426 | 426 | ||
427 | /* can not fail */ | ||
428 | static int __devinit correct_chipset(struct atyfb_par *par) | 427 | static int __devinit correct_chipset(struct atyfb_par *par) |
429 | { | 428 | { |
430 | u8 rev; | 429 | u8 rev; |
@@ -437,6 +436,9 @@ static int __devinit correct_chipset(struct atyfb_par *par) | |||
437 | if (par->pci_id == aty_chips[i].pci_id) | 436 | if (par->pci_id == aty_chips[i].pci_id) |
438 | break; | 437 | break; |
439 | 438 | ||
439 | if (i < 0) | ||
440 | return -ENODEV; | ||
441 | |||
440 | name = aty_chips[i].name; | 442 | name = aty_chips[i].name; |
441 | par->pll_limits.pll_max = aty_chips[i].pll; | 443 | par->pll_limits.pll_max = aty_chips[i].pll; |
442 | par->pll_limits.mclk = aty_chips[i].mclk; | 444 | par->pll_limits.mclk = aty_chips[i].mclk; |
@@ -2021,6 +2023,20 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2021 | return 0; | 2023 | return 0; |
2022 | } | 2024 | } |
2023 | 2025 | ||
2026 | static void aty_resume_chip(struct fb_info *info) | ||
2027 | { | ||
2028 | struct atyfb_par *par = info->par; | ||
2029 | |||
2030 | aty_st_le32(MEM_CNTL, par->mem_cntl, par); | ||
2031 | |||
2032 | if (par->pll_ops->resume_pll) | ||
2033 | par->pll_ops->resume_pll(info, &par->pll); | ||
2034 | |||
2035 | if (par->aux_start) | ||
2036 | aty_st_le32(BUS_CNTL, | ||
2037 | aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); | ||
2038 | } | ||
2039 | |||
2024 | static int atyfb_pci_resume(struct pci_dev *pdev) | 2040 | static int atyfb_pci_resume(struct pci_dev *pdev) |
2025 | { | 2041 | { |
2026 | struct fb_info *info = pci_get_drvdata(pdev); | 2042 | struct fb_info *info = pci_get_drvdata(pdev); |
@@ -2229,6 +2245,7 @@ static int __devinit aty_init(struct fb_info *info) | |||
2229 | const char *ramname = NULL, *xtal; | 2245 | const char *ramname = NULL, *xtal; |
2230 | int gtb_memsize, has_var = 0; | 2246 | int gtb_memsize, has_var = 0; |
2231 | struct fb_var_screeninfo var; | 2247 | struct fb_var_screeninfo var; |
2248 | int ret; | ||
2232 | 2249 | ||
2233 | init_waitqueue_head(&par->vblank.wait); | 2250 | init_waitqueue_head(&par->vblank.wait); |
2234 | spin_lock_init(&par->int_lock); | 2251 | spin_lock_init(&par->int_lock); |
@@ -2610,7 +2627,8 @@ static int __devinit aty_init(struct fb_info *info) | |||
2610 | var.yres_virtual = var.yres; | 2627 | var.yres_virtual = var.yres; |
2611 | } | 2628 | } |
2612 | 2629 | ||
2613 | if (atyfb_check_var(&var, info)) { | 2630 | ret = atyfb_check_var(&var, info); |
2631 | if (ret) { | ||
2614 | PRINTKE("can't set default video mode\n"); | 2632 | PRINTKE("can't set default video mode\n"); |
2615 | goto aty_init_exit; | 2633 | goto aty_init_exit; |
2616 | } | 2634 | } |
@@ -2621,10 +2639,12 @@ static int __devinit aty_init(struct fb_info *info) | |||
2621 | #endif /* CONFIG_FB_ATY_CT */ | 2639 | #endif /* CONFIG_FB_ATY_CT */ |
2622 | info->var = var; | 2640 | info->var = var; |
2623 | 2641 | ||
2624 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) | 2642 | ret = fb_alloc_cmap(&info->cmap, 256, 0); |
2643 | if (ret < 0) | ||
2625 | goto aty_init_exit; | 2644 | goto aty_init_exit; |
2626 | 2645 | ||
2627 | if (register_framebuffer(info) < 0) { | 2646 | ret = register_framebuffer(info); |
2647 | if (ret < 0) { | ||
2628 | fb_dealloc_cmap(&info->cmap); | 2648 | fb_dealloc_cmap(&info->cmap); |
2629 | goto aty_init_exit; | 2649 | goto aty_init_exit; |
2630 | } | 2650 | } |
@@ -2650,20 +2670,7 @@ aty_init_exit: | |||
2650 | par->mtrr_aper = -1; | 2670 | par->mtrr_aper = -1; |
2651 | } | 2671 | } |
2652 | #endif | 2672 | #endif |
2653 | return -1; | 2673 | return ret; |
2654 | } | ||
2655 | |||
2656 | static void aty_resume_chip(struct fb_info *info) | ||
2657 | { | ||
2658 | struct atyfb_par *par = info->par; | ||
2659 | |||
2660 | aty_st_le32(MEM_CNTL, par->mem_cntl, par); | ||
2661 | |||
2662 | if (par->pll_ops->resume_pll) | ||
2663 | par->pll_ops->resume_pll(info, &par->pll); | ||
2664 | |||
2665 | if (par->aux_start) | ||
2666 | aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); | ||
2667 | } | 2674 | } |
2668 | 2675 | ||
2669 | #ifdef CONFIG_ATARI | 2676 | #ifdef CONFIG_ATARI |
@@ -2709,8 +2716,7 @@ static int atyfb_blank(int blank, struct fb_info *info) | |||
2709 | if (par->lock_blank || par->asleep) | 2716 | if (par->lock_blank || par->asleep) |
2710 | return 0; | 2717 | return 0; |
2711 | 2718 | ||
2712 | #ifdef CONFIG_FB_ATY_BACKLIGHT | 2719 | #ifdef CONFIG_FB_ATY_GENERIC_LCD |
2713 | #elif defined(CONFIG_FB_ATY_GENERIC_LCD) | ||
2714 | if (par->lcd_table && blank > FB_BLANK_NORMAL && | 2720 | if (par->lcd_table && blank > FB_BLANK_NORMAL && |
2715 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { | 2721 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { |
2716 | u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); | 2722 | u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); |
@@ -2739,8 +2745,7 @@ static int atyfb_blank(int blank, struct fb_info *info) | |||
2739 | } | 2745 | } |
2740 | aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); | 2746 | aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); |
2741 | 2747 | ||
2742 | #ifdef CONFIG_FB_ATY_BACKLIGHT | 2748 | #ifdef CONFIG_FB_ATY_GENERIC_LCD |
2743 | #elif defined(CONFIG_FB_ATY_GENERIC_LCD) | ||
2744 | if (par->lcd_table && blank <= FB_BLANK_NORMAL && | 2749 | if (par->lcd_table && blank <= FB_BLANK_NORMAL && |
2745 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { | 2750 | (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { |
2746 | u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); | 2751 | u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); |
@@ -3331,7 +3336,7 @@ static int __devinit init_from_bios(struct atyfb_par *par) | |||
3331 | PRINTKE("no BIOS frequency table found, use parameters\n"); | 3336 | PRINTKE("no BIOS frequency table found, use parameters\n"); |
3332 | ret = -ENXIO; | 3337 | ret = -ENXIO; |
3333 | } | 3338 | } |
3334 | iounmap((void* __iomem )bios_base); | 3339 | iounmap((void __iomem *)bios_base); |
3335 | 3340 | ||
3336 | return ret; | 3341 | return ret; |
3337 | } | 3342 | } |
@@ -3418,14 +3423,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
3418 | struct fb_info *info; | 3423 | struct fb_info *info; |
3419 | struct resource *rp; | 3424 | struct resource *rp; |
3420 | struct atyfb_par *par; | 3425 | struct atyfb_par *par; |
3421 | int i, rc = -ENOMEM; | 3426 | int rc = -ENOMEM; |
3422 | |||
3423 | for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--) | ||
3424 | if (pdev->device == aty_chips[i].pci_id) | ||
3425 | break; | ||
3426 | |||
3427 | if (i < 0) | ||
3428 | return -ENODEV; | ||
3429 | 3427 | ||
3430 | /* Enable device in PCI config */ | 3428 | /* Enable device in PCI config */ |
3431 | if (pci_enable_device(pdev)) { | 3429 | if (pci_enable_device(pdev)) { |
@@ -3456,7 +3454,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
3456 | par = info->par; | 3454 | par = info->par; |
3457 | info->fix = atyfb_fix; | 3455 | info->fix = atyfb_fix; |
3458 | info->device = &pdev->dev; | 3456 | info->device = &pdev->dev; |
3459 | par->pci_id = aty_chips[i].pci_id; | 3457 | par->pci_id = pdev->device; |
3460 | par->res_start = res_start; | 3458 | par->res_start = res_start; |
3461 | par->res_size = res_size; | 3459 | par->res_size = res_size; |
3462 | par->irq = pdev->irq; | 3460 | par->irq = pdev->irq; |
@@ -3474,7 +3472,8 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
3474 | pci_set_drvdata(pdev, info); | 3472 | pci_set_drvdata(pdev, info); |
3475 | 3473 | ||
3476 | /* Init chip & register framebuffer */ | 3474 | /* Init chip & register framebuffer */ |
3477 | if (aty_init(info)) | 3475 | rc = aty_init(info); |
3476 | if (rc) | ||
3478 | goto err_release_io; | 3477 | goto err_release_io; |
3479 | 3478 | ||
3480 | #ifdef __sparc__ | 3479 | #ifdef __sparc__ |
@@ -3655,18 +3654,62 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev) | |||
3655 | atyfb_remove(info); | 3654 | atyfb_remove(info); |
3656 | } | 3655 | } |
3657 | 3656 | ||
3658 | /* | ||
3659 | * This driver uses its own matching table. That will be more difficult | ||
3660 | * to fix, so for now, we just match against any ATI ID and let the | ||
3661 | * probe() function find out what's up. That also mean we don't have | ||
3662 | * a module ID table though. | ||
3663 | */ | ||
3664 | static struct pci_device_id atyfb_pci_tbl[] = { | 3657 | static struct pci_device_id atyfb_pci_tbl[] = { |
3665 | { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 3658 | #ifdef CONFIG_FB_ATY_GX |
3666 | PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 }, | 3659 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) }, |
3667 | { 0, } | 3660 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) }, |
3661 | #endif /* CONFIG_FB_ATY_GX */ | ||
3662 | |||
3663 | #ifdef CONFIG_FB_ATY_CT | ||
3664 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) }, | ||
3665 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) }, | ||
3666 | |||
3667 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) }, | ||
3668 | |||
3669 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) }, | ||
3670 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) }, | ||
3671 | |||
3672 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) }, | ||
3673 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) }, | ||
3674 | |||
3675 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) }, | ||
3676 | |||
3677 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) }, | ||
3678 | |||
3679 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) }, | ||
3680 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) }, | ||
3681 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) }, | ||
3682 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) }, | ||
3683 | |||
3684 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) }, | ||
3685 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) }, | ||
3686 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) }, | ||
3687 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) }, | ||
3688 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) }, | ||
3689 | |||
3690 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) }, | ||
3691 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) }, | ||
3692 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) }, | ||
3693 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) }, | ||
3694 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) }, | ||
3695 | |||
3696 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) }, | ||
3697 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) }, | ||
3698 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) }, | ||
3699 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) }, | ||
3700 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) }, | ||
3701 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) }, | ||
3702 | |||
3703 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) }, | ||
3704 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) }, | ||
3705 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) }, | ||
3706 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) }, | ||
3707 | #endif /* CONFIG_FB_ATY_CT */ | ||
3708 | { } | ||
3668 | }; | 3709 | }; |
3669 | 3710 | ||
3711 | MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl); | ||
3712 | |||
3670 | static struct pci_driver atyfb_driver = { | 3713 | static struct pci_driver atyfb_driver = { |
3671 | .name = "atyfb", | 3714 | .name = "atyfb", |
3672 | .id_table = atyfb_pci_tbl, | 3715 | .id_table = atyfb_pci_tbl, |
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index 3ca27cb13caa..aa95f8350242 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c | |||
@@ -55,6 +55,10 @@ static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, | |||
55 | OUTREG(DP_WRITE_MSK, 0xffffffff); | 55 | OUTREG(DP_WRITE_MSK, 0xffffffff); |
56 | OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); | 56 | OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); |
57 | 57 | ||
58 | radeon_fifo_wait(2); | ||
59 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | ||
60 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | ||
61 | |||
58 | radeon_fifo_wait(2); | 62 | radeon_fifo_wait(2); |
59 | OUTREG(DST_Y_X, (region->dy << 16) | region->dx); | 63 | OUTREG(DST_Y_X, (region->dy << 16) | region->dx); |
60 | OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); | 64 | OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); |
@@ -116,6 +120,10 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, | |||
116 | OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) | 120 | OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
117 | | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); | 121 | | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); |
118 | 122 | ||
123 | radeon_fifo_wait(2); | ||
124 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | ||
125 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | ||
126 | |||
119 | radeon_fifo_wait(3); | 127 | radeon_fifo_wait(3); |
120 | OUTREG(SRC_Y_X, (sy << 16) | sx); | 128 | OUTREG(SRC_Y_X, (sy << 16) | sx); |
121 | OUTREG(DST_Y_X, (dy << 16) | dx); | 129 | OUTREG(DST_Y_X, (dy << 16) | dx); |
@@ -241,8 +249,8 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo) | |||
241 | INREG(HOST_PATH_CNTL); | 249 | INREG(HOST_PATH_CNTL); |
242 | OUTREG(HOST_PATH_CNTL, host_path_cntl); | 250 | OUTREG(HOST_PATH_CNTL, host_path_cntl); |
243 | 251 | ||
244 | if (rinfo->family != CHIP_FAMILY_R300 || | 252 | if (rinfo->family != CHIP_FAMILY_R300 && |
245 | rinfo->family != CHIP_FAMILY_R350 || | 253 | rinfo->family != CHIP_FAMILY_R350 && |
246 | rinfo->family != CHIP_FAMILY_RV350) | 254 | rinfo->family != CHIP_FAMILY_RV350) |
247 | OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); | 255 | OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); |
248 | 256 | ||
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 400e9264e456..652273e9f5f9 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -2098,15 +2098,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) | |||
2098 | 2098 | ||
2099 | static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid) | 2099 | static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid) |
2100 | { | 2100 | { |
2101 | if (off > EDID_LENGTH) | 2101 | return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH); |
2102 | return 0; | ||
2103 | |||
2104 | if (off + count > EDID_LENGTH) | ||
2105 | count = EDID_LENGTH - off; | ||
2106 | |||
2107 | memcpy(buf, edid + off, count); | ||
2108 | |||
2109 | return count; | ||
2110 | } | 2102 | } |
2111 | 2103 | ||
2112 | 2104 | ||
@@ -2161,6 +2153,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, | |||
2161 | struct radeonfb_info *rinfo; | 2153 | struct radeonfb_info *rinfo; |
2162 | int ret; | 2154 | int ret; |
2163 | unsigned char c1, c2; | 2155 | unsigned char c1, c2; |
2156 | int err = 0; | ||
2164 | 2157 | ||
2165 | pr_debug("radeonfb_pci_register BEGIN\n"); | 2158 | pr_debug("radeonfb_pci_register BEGIN\n"); |
2166 | 2159 | ||
@@ -2340,9 +2333,14 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, | |||
2340 | 2333 | ||
2341 | /* Register some sysfs stuff (should be done better) */ | 2334 | /* Register some sysfs stuff (should be done better) */ |
2342 | if (rinfo->mon1_EDID) | 2335 | if (rinfo->mon1_EDID) |
2343 | sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr); | 2336 | err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj, |
2337 | &edid1_attr); | ||
2344 | if (rinfo->mon2_EDID) | 2338 | if (rinfo->mon2_EDID) |
2345 | sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr); | 2339 | err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj, |
2340 | &edid2_attr); | ||
2341 | if (err) | ||
2342 | pr_warning("%s() Creating sysfs files failed, continuing\n", | ||
2343 | __func__); | ||
2346 | 2344 | ||
2347 | /* save current mode regs before we switch into the new one | 2345 | /* save current mode regs before we switch into the new one |
2348 | * so we can restore this upon __exit | 2346 | * so we can restore this upon __exit |
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index f9e7c29ad9bf..8c8fa35f1b7c 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c | |||
@@ -69,7 +69,8 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name) | |||
69 | { | 69 | { |
70 | int rc; | 70 | int rc; |
71 | 71 | ||
72 | strcpy(chan->adapter.name, name); | 72 | snprintf(chan->adapter.name, sizeof(chan->adapter.name), |
73 | "radeonfb %s", name); | ||
73 | chan->adapter.owner = THIS_MODULE; | 74 | chan->adapter.owner = THIS_MODULE; |
74 | chan->adapter.id = I2C_HW_B_RADEON; | 75 | chan->adapter.id = I2C_HW_B_RADEON; |
75 | chan->adapter.algo_data = &chan->algo; | 76 | chan->adapter.algo_data = &chan->algo; |
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index c347e38cd0b0..ccbfffd12805 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h | |||
@@ -289,7 +289,7 @@ struct radeonfb_info { | |||
289 | struct radeon_regs state; | 289 | struct radeon_regs state; |
290 | struct radeon_regs init_state; | 290 | struct radeon_regs init_state; |
291 | 291 | ||
292 | char name[DEVICE_NAME_SIZE]; | 292 | char name[50]; |
293 | 293 | ||
294 | unsigned long mmio_base_phys; | 294 | unsigned long mmio_base_phys; |
295 | unsigned long fb_base_phys; | 295 | unsigned long fb_base_phys; |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 30bf7f2f1635..452b770d8cc9 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -36,6 +36,30 @@ config LCD_LTV350QV | |||
36 | 36 | ||
37 | The LTV350QV panel is present on all ATSTK1000 boards. | 37 | The LTV350QV panel is present on all ATSTK1000 boards. |
38 | 38 | ||
39 | config LCD_ILI9320 | ||
40 | tristate | ||
41 | depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT | ||
42 | default n | ||
43 | help | ||
44 | If you have a panel based on the ILI9320 controller chip | ||
45 | then say y to include a power driver for it. | ||
46 | |||
47 | config LCD_VGG2432A4 | ||
48 | tristate "VGG2432A4 LCM device support" | ||
49 | depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER | ||
50 | select LCD_ILI9320 | ||
51 | default n | ||
52 | help | ||
53 | If you have a VGG2432A4 panel based on the ILI9320 controller chip | ||
54 | then say y to include a power driver for it. | ||
55 | |||
56 | config LCD_PLATFORM | ||
57 | tristate "Platform LCD controls" | ||
58 | depends on LCD_CLASS_DEVICE | ||
59 | help | ||
60 | This driver provides a platform-device registered LCD power | ||
61 | control interface. | ||
62 | |||
39 | # | 63 | # |
40 | # Backlight | 64 | # Backlight |
41 | # | 65 | # |
@@ -63,6 +87,18 @@ config BACKLIGHT_ATMEL_LCDC | |||
63 | If in doubt, it's safe to enable this option; it doesn't kick | 87 | If in doubt, it's safe to enable this option; it doesn't kick |
64 | in unless the board's description says it's wired that way. | 88 | in unless the board's description says it's wired that way. |
65 | 89 | ||
90 | config BACKLIGHT_ATMEL_PWM | ||
91 | tristate "Atmel PWM backlight control" | ||
92 | depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM | ||
93 | default n | ||
94 | help | ||
95 | Say Y here if you want to use the PWM peripheral in Atmel AT91 and | ||
96 | AVR32 devices. This driver will need additional platform data to know | ||
97 | which PWM instance to use and how to configure it. | ||
98 | |||
99 | To compile this driver as a module, choose M here: the module will be | ||
100 | called atmel-pwm-bl. | ||
101 | |||
66 | config BACKLIGHT_CORGI | 102 | config BACKLIGHT_CORGI |
67 | tristate "Generic (aka Sharp Corgi) Backlight Driver" | 103 | tristate "Generic (aka Sharp Corgi) Backlight Driver" |
68 | depends on BACKLIGHT_CLASS_DEVICE | 104 | depends on BACKLIGHT_CLASS_DEVICE |
@@ -119,3 +155,12 @@ config BACKLIGHT_PWM | |||
119 | help | 155 | help |
120 | If you have a LCD backlight adjustable by PWM, say Y to enable | 156 | If you have a LCD backlight adjustable by PWM, say Y to enable |
121 | this driver. | 157 | this driver. |
158 | |||
159 | config BACKLIGHT_MBP_NVIDIA | ||
160 | tristate "MacBook Pro Nvidia Backlight Driver" | ||
161 | depends on BACKLIGHT_CLASS_DEVICE && X86 | ||
162 | default n | ||
163 | help | ||
164 | If you have an Apple Macbook Pro with Nvidia graphics hardware say Y | ||
165 | to enable a driver for its backlight | ||
166 | |||
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index b51a7cd12500..b405aace803f 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -1,9 +1,13 @@ | |||
1 | # Backlight & LCD drivers | 1 | # Backlight & LCD drivers |
2 | 2 | ||
3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o | 3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o |
4 | obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o | 4 | obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o |
5 | obj-$(CONFIG_LCD_ILI9320) += ili9320.o | ||
6 | obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o | ||
7 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o | ||
5 | 8 | ||
6 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o | 9 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o |
10 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o | ||
7 | obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o | 11 | obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o |
8 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o | 12 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o |
9 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o | 13 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o |
@@ -11,3 +15,5 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | |||
11 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | 15 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o |
12 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 16 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
13 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | 17 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o |
18 | obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o | ||
19 | |||
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c new file mode 100644 index 000000000000..505c0823a105 --- /dev/null +++ b/drivers/video/backlight/atmel-pwm-bl.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Atmel Corporation | ||
3 | * | ||
4 | * Backlight driver using Atmel PWM peripheral. | ||
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 version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/fb.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/backlight.h> | ||
18 | #include <linux/atmel_pwm.h> | ||
19 | #include <linux/atmel-pwm-bl.h> | ||
20 | |||
21 | struct atmel_pwm_bl { | ||
22 | const struct atmel_pwm_bl_platform_data *pdata; | ||
23 | struct backlight_device *bldev; | ||
24 | struct platform_device *pdev; | ||
25 | struct pwm_channel pwmc; | ||
26 | int gpio_on; | ||
27 | }; | ||
28 | |||
29 | static int atmel_pwm_bl_set_intensity(struct backlight_device *bd) | ||
30 | { | ||
31 | struct atmel_pwm_bl *pwmbl = bl_get_data(bd); | ||
32 | int intensity = bd->props.brightness; | ||
33 | int pwm_duty; | ||
34 | |||
35 | if (bd->props.power != FB_BLANK_UNBLANK) | ||
36 | intensity = 0; | ||
37 | if (bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
38 | intensity = 0; | ||
39 | |||
40 | if (pwmbl->pdata->pwm_active_low) | ||
41 | pwm_duty = pwmbl->pdata->pwm_duty_min + intensity; | ||
42 | else | ||
43 | pwm_duty = pwmbl->pdata->pwm_duty_max - intensity; | ||
44 | |||
45 | if (pwm_duty > pwmbl->pdata->pwm_duty_max) | ||
46 | pwm_duty = pwmbl->pdata->pwm_duty_max; | ||
47 | if (pwm_duty < pwmbl->pdata->pwm_duty_min) | ||
48 | pwm_duty = pwmbl->pdata->pwm_duty_min; | ||
49 | |||
50 | if (!intensity) { | ||
51 | if (pwmbl->gpio_on != -1) { | ||
52 | gpio_set_value(pwmbl->gpio_on, | ||
53 | 0 ^ pwmbl->pdata->on_active_low); | ||
54 | } | ||
55 | pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty); | ||
56 | pwm_channel_disable(&pwmbl->pwmc); | ||
57 | } else { | ||
58 | pwm_channel_enable(&pwmbl->pwmc); | ||
59 | pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty); | ||
60 | if (pwmbl->gpio_on != -1) { | ||
61 | gpio_set_value(pwmbl->gpio_on, | ||
62 | 1 ^ pwmbl->pdata->on_active_low); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int atmel_pwm_bl_get_intensity(struct backlight_device *bd) | ||
70 | { | ||
71 | struct atmel_pwm_bl *pwmbl = bl_get_data(bd); | ||
72 | u8 intensity; | ||
73 | |||
74 | if (pwmbl->pdata->pwm_active_low) { | ||
75 | intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) - | ||
76 | pwmbl->pdata->pwm_duty_min; | ||
77 | } else { | ||
78 | intensity = pwmbl->pdata->pwm_duty_max - | ||
79 | pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY); | ||
80 | } | ||
81 | |||
82 | return intensity; | ||
83 | } | ||
84 | |||
85 | static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl) | ||
86 | { | ||
87 | unsigned long pwm_rate = pwmbl->pwmc.mck; | ||
88 | unsigned long prescale = DIV_ROUND_UP(pwm_rate, | ||
89 | (pwmbl->pdata->pwm_frequency * | ||
90 | pwmbl->pdata->pwm_compare_max)) - 1; | ||
91 | |||
92 | /* | ||
93 | * Prescale must be power of two and maximum 0xf in size because of | ||
94 | * hardware limit. PWM speed will be: | ||
95 | * PWM module clock speed / (2 ^ prescale). | ||
96 | */ | ||
97 | prescale = fls(prescale); | ||
98 | if (prescale > 0xf) | ||
99 | prescale = 0xf; | ||
100 | |||
101 | pwm_channel_writel(&pwmbl->pwmc, PWM_CMR, prescale); | ||
102 | pwm_channel_writel(&pwmbl->pwmc, PWM_CDTY, | ||
103 | pwmbl->pdata->pwm_duty_min + | ||
104 | pwmbl->bldev->props.brightness); | ||
105 | pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD, | ||
106 | pwmbl->pdata->pwm_compare_max); | ||
107 | |||
108 | dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver " | ||
109 | "(%lu Hz)\n", pwmbl->pwmc.mck / | ||
110 | pwmbl->pdata->pwm_compare_max / | ||
111 | (1 << prescale)); | ||
112 | |||
113 | return pwm_channel_enable(&pwmbl->pwmc); | ||
114 | } | ||
115 | |||
116 | static struct backlight_ops atmel_pwm_bl_ops = { | ||
117 | .get_brightness = atmel_pwm_bl_get_intensity, | ||
118 | .update_status = atmel_pwm_bl_set_intensity, | ||
119 | }; | ||
120 | |||
121 | static int atmel_pwm_bl_probe(struct platform_device *pdev) | ||
122 | { | ||
123 | const struct atmel_pwm_bl_platform_data *pdata; | ||
124 | struct backlight_device *bldev; | ||
125 | struct atmel_pwm_bl *pwmbl; | ||
126 | int retval; | ||
127 | |||
128 | pwmbl = kzalloc(sizeof(struct atmel_pwm_bl), GFP_KERNEL); | ||
129 | if (!pwmbl) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | pwmbl->pdev = pdev; | ||
133 | |||
134 | pdata = pdev->dev.platform_data; | ||
135 | if (!pdata) { | ||
136 | retval = -ENODEV; | ||
137 | goto err_free_mem; | ||
138 | } | ||
139 | |||
140 | if (pdata->pwm_compare_max < pdata->pwm_duty_max || | ||
141 | pdata->pwm_duty_min > pdata->pwm_duty_max || | ||
142 | pdata->pwm_frequency == 0) { | ||
143 | retval = -EINVAL; | ||
144 | goto err_free_mem; | ||
145 | } | ||
146 | |||
147 | pwmbl->pdata = pdata; | ||
148 | pwmbl->gpio_on = pdata->gpio_on; | ||
149 | |||
150 | retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc); | ||
151 | if (retval) | ||
152 | goto err_free_mem; | ||
153 | |||
154 | if (pwmbl->gpio_on != -1) { | ||
155 | retval = gpio_request(pwmbl->gpio_on, "gpio_atmel_pwm_bl"); | ||
156 | if (retval) { | ||
157 | pwmbl->gpio_on = -1; | ||
158 | goto err_free_pwm; | ||
159 | } | ||
160 | |||
161 | /* Turn display off by defatult. */ | ||
162 | retval = gpio_direction_output(pwmbl->gpio_on, | ||
163 | 0 ^ pdata->on_active_low); | ||
164 | if (retval) | ||
165 | goto err_free_gpio; | ||
166 | } | ||
167 | |||
168 | bldev = backlight_device_register("atmel-pwm-bl", | ||
169 | &pdev->dev, pwmbl, &atmel_pwm_bl_ops); | ||
170 | if (IS_ERR(bldev)) { | ||
171 | retval = PTR_ERR(bldev); | ||
172 | goto err_free_gpio; | ||
173 | } | ||
174 | |||
175 | pwmbl->bldev = bldev; | ||
176 | |||
177 | platform_set_drvdata(pdev, pwmbl); | ||
178 | |||
179 | /* Power up the backlight by default at middle intesity. */ | ||
180 | bldev->props.power = FB_BLANK_UNBLANK; | ||
181 | bldev->props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min; | ||
182 | bldev->props.brightness = bldev->props.max_brightness / 2; | ||
183 | |||
184 | retval = atmel_pwm_bl_init_pwm(pwmbl); | ||
185 | if (retval) | ||
186 | goto err_free_bl_dev; | ||
187 | |||
188 | atmel_pwm_bl_set_intensity(bldev); | ||
189 | |||
190 | return 0; | ||
191 | |||
192 | err_free_bl_dev: | ||
193 | platform_set_drvdata(pdev, NULL); | ||
194 | backlight_device_unregister(bldev); | ||
195 | err_free_gpio: | ||
196 | if (pwmbl->gpio_on != -1) | ||
197 | gpio_free(pwmbl->gpio_on); | ||
198 | err_free_pwm: | ||
199 | pwm_channel_free(&pwmbl->pwmc); | ||
200 | err_free_mem: | ||
201 | kfree(pwmbl); | ||
202 | return retval; | ||
203 | } | ||
204 | |||
205 | static int __exit atmel_pwm_bl_remove(struct platform_device *pdev) | ||
206 | { | ||
207 | struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev); | ||
208 | |||
209 | if (pwmbl->gpio_on != -1) { | ||
210 | gpio_set_value(pwmbl->gpio_on, 0); | ||
211 | gpio_free(pwmbl->gpio_on); | ||
212 | } | ||
213 | pwm_channel_disable(&pwmbl->pwmc); | ||
214 | pwm_channel_free(&pwmbl->pwmc); | ||
215 | backlight_device_unregister(pwmbl->bldev); | ||
216 | platform_set_drvdata(pdev, NULL); | ||
217 | kfree(pwmbl); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static struct platform_driver atmel_pwm_bl_driver = { | ||
223 | .driver = { | ||
224 | .name = "atmel-pwm-bl", | ||
225 | }, | ||
226 | /* REVISIT add suspend() and resume() */ | ||
227 | .remove = __exit_p(atmel_pwm_bl_remove), | ||
228 | }; | ||
229 | |||
230 | static int __init atmel_pwm_bl_init(void) | ||
231 | { | ||
232 | return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe); | ||
233 | } | ||
234 | module_init(atmel_pwm_bl_init); | ||
235 | |||
236 | static void __exit atmel_pwm_bl_exit(void) | ||
237 | { | ||
238 | platform_driver_unregister(&atmel_pwm_bl_driver); | ||
239 | } | ||
240 | module_exit(atmel_pwm_bl_exit); | ||
241 | |||
242 | MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>"); | ||
243 | MODULE_DESCRIPTION("Atmel PWM backlight driver"); | ||
244 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 39394757679c..fab0bc874b58 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -191,6 +191,7 @@ static struct device_attribute bl_device_attributes[] = { | |||
191 | * backlight_device class. | 191 | * backlight_device class. |
192 | * @name: the name of the new object(must be the same as the name of the | 192 | * @name: the name of the new object(must be the same as the name of the |
193 | * respective framebuffer device). | 193 | * respective framebuffer device). |
194 | * @parent: a pointer to the parent device | ||
194 | * @devdata: an optional pointer to be stored for private driver use. The | 195 | * @devdata: an optional pointer to be stored for private driver use. The |
195 | * methods may retrieve it by using bl_get_data(bd). | 196 | * methods may retrieve it by using bl_get_data(bd). |
196 | * @ops: the backlight operations structure. | 197 | * @ops: the backlight operations structure. |
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index fbea2bd129c7..6fa0b9d5559a 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/fb.h> | 18 | #include <linux/fb.h> |
19 | #include <linux/backlight.h> | 19 | #include <linux/backlight.h> |
20 | 20 | ||
21 | #include <asm/cpu/dac.h> | 21 | #include <cpu/dac.h> |
22 | #include <asm/hp6xx.h> | 22 | #include <asm/hp6xx.h> |
23 | #include <asm/hd64461.h> | 23 | #include <asm/hd64461.h> |
24 | 24 | ||
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c new file mode 100644 index 000000000000..ba89b41b639c --- /dev/null +++ b/drivers/video/backlight/ili9320.c | |||
@@ -0,0 +1,330 @@ | |||
1 | /* drivers/video/backlight/ili9320.c | ||
2 | * | ||
3 | * ILI9320 LCD controller driver core. | ||
4 | * | ||
5 | * Copyright 2007 Simtec Electronics | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * Ben Dooks <ben@simtec.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/fb.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/lcd.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <linux/spi/spi.h> | ||
22 | |||
23 | #include <video/ili9320.h> | ||
24 | |||
25 | #include "ili9320.h" | ||
26 | |||
27 | |||
28 | static inline int ili9320_write_spi(struct ili9320 *ili, | ||
29 | unsigned int reg, | ||
30 | unsigned int value) | ||
31 | { | ||
32 | struct ili9320_spi *spi = &ili->access.spi; | ||
33 | unsigned char *addr = spi->buffer_addr; | ||
34 | unsigned char *data = spi->buffer_data; | ||
35 | |||
36 | /* spi message consits of: | ||
37 | * first byte: ID and operation | ||
38 | */ | ||
39 | |||
40 | addr[0] = spi->id | ILI9320_SPI_INDEX | ILI9320_SPI_WRITE; | ||
41 | addr[1] = reg >> 8; | ||
42 | addr[2] = reg; | ||
43 | |||
44 | /* second message is the data to transfer */ | ||
45 | |||
46 | data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE; | ||
47 | data[1] = value >> 8; | ||
48 | data[2] = value; | ||
49 | |||
50 | return spi_sync(spi->dev, &spi->message); | ||
51 | } | ||
52 | |||
53 | int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value) | ||
54 | { | ||
55 | dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value); | ||
56 | return ili->write(ili, reg, value); | ||
57 | } | ||
58 | |||
59 | EXPORT_SYMBOL_GPL(ili9320_write); | ||
60 | |||
61 | int ili9320_write_regs(struct ili9320 *ili, | ||
62 | struct ili9320_reg *values, | ||
63 | int nr_values) | ||
64 | { | ||
65 | int index; | ||
66 | int ret; | ||
67 | |||
68 | for (index = 0; index < nr_values; index++, values++) { | ||
69 | ret = ili9320_write(ili, values->address, values->value); | ||
70 | if (ret != 0) | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | EXPORT_SYMBOL_GPL(ili9320_write_regs); | ||
78 | |||
79 | static void ili9320_reset(struct ili9320 *lcd) | ||
80 | { | ||
81 | struct ili9320_platdata *cfg = lcd->platdata; | ||
82 | |||
83 | cfg->reset(1); | ||
84 | mdelay(50); | ||
85 | |||
86 | cfg->reset(0); | ||
87 | mdelay(50); | ||
88 | |||
89 | cfg->reset(1); | ||
90 | mdelay(100); | ||
91 | } | ||
92 | |||
93 | static inline int ili9320_init_chip(struct ili9320 *lcd) | ||
94 | { | ||
95 | int ret; | ||
96 | |||
97 | ili9320_reset(lcd); | ||
98 | |||
99 | ret = lcd->client->init(lcd, lcd->platdata); | ||
100 | if (ret != 0) { | ||
101 | dev_err(lcd->dev, "failed to initialise display\n"); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | lcd->initialised = 1; | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static inline int ili9320_power_on(struct ili9320 *lcd) | ||
110 | { | ||
111 | if (!lcd->initialised) | ||
112 | ili9320_init_chip(lcd); | ||
113 | |||
114 | lcd->display1 |= (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE); | ||
115 | ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static inline int ili9320_power_off(struct ili9320 *lcd) | ||
121 | { | ||
122 | lcd->display1 &= ~(ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE); | ||
123 | ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) | ||
129 | |||
130 | static int ili9320_power(struct ili9320 *lcd, int power) | ||
131 | { | ||
132 | int ret = 0; | ||
133 | |||
134 | dev_dbg(lcd->dev, "power %d => %d\n", lcd->power, power); | ||
135 | |||
136 | if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) | ||
137 | ret = ili9320_power_on(lcd); | ||
138 | else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) | ||
139 | ret = ili9320_power_off(lcd); | ||
140 | |||
141 | if (ret == 0) | ||
142 | lcd->power = power; | ||
143 | else | ||
144 | dev_warn(lcd->dev, "failed to set power mode %d\n", power); | ||
145 | |||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | static inline struct ili9320 *to_our_lcd(struct lcd_device *lcd) | ||
150 | { | ||
151 | return lcd_get_data(lcd); | ||
152 | } | ||
153 | |||
154 | static int ili9320_set_power(struct lcd_device *ld, int power) | ||
155 | { | ||
156 | struct ili9320 *lcd = to_our_lcd(ld); | ||
157 | |||
158 | return ili9320_power(lcd, power); | ||
159 | } | ||
160 | |||
161 | static int ili9320_get_power(struct lcd_device *ld) | ||
162 | { | ||
163 | struct ili9320 *lcd = to_our_lcd(ld); | ||
164 | |||
165 | return lcd->power; | ||
166 | } | ||
167 | |||
168 | static struct lcd_ops ili9320_ops = { | ||
169 | .get_power = ili9320_get_power, | ||
170 | .set_power = ili9320_set_power, | ||
171 | }; | ||
172 | |||
173 | static void __devinit ili9320_setup_spi(struct ili9320 *ili, | ||
174 | struct spi_device *dev) | ||
175 | { | ||
176 | struct ili9320_spi *spi = &ili->access.spi; | ||
177 | |||
178 | ili->write = ili9320_write_spi; | ||
179 | spi->dev = dev; | ||
180 | |||
181 | /* fill the two messages we are going to use to send the data | ||
182 | * with, the first the address followed by the data. The datasheet | ||
183 | * says they should be done as two distinct cycles of the SPI CS line. | ||
184 | */ | ||
185 | |||
186 | spi->xfer[0].tx_buf = spi->buffer_addr; | ||
187 | spi->xfer[1].tx_buf = spi->buffer_data; | ||
188 | spi->xfer[0].len = 3; | ||
189 | spi->xfer[1].len = 3; | ||
190 | spi->xfer[0].bits_per_word = 8; | ||
191 | spi->xfer[1].bits_per_word = 8; | ||
192 | spi->xfer[0].cs_change = 1; | ||
193 | |||
194 | spi_message_init(&spi->message); | ||
195 | spi_message_add_tail(&spi->xfer[0], &spi->message); | ||
196 | spi_message_add_tail(&spi->xfer[1], &spi->message); | ||
197 | } | ||
198 | |||
199 | int __devinit ili9320_probe_spi(struct spi_device *spi, | ||
200 | struct ili9320_client *client) | ||
201 | { | ||
202 | struct ili9320_platdata *cfg = spi->dev.platform_data; | ||
203 | struct device *dev = &spi->dev; | ||
204 | struct ili9320 *ili; | ||
205 | struct lcd_device *lcd; | ||
206 | int ret = 0; | ||
207 | |||
208 | /* verify we where given some information */ | ||
209 | |||
210 | if (cfg == NULL) { | ||
211 | dev_err(dev, "no platform data supplied\n"); | ||
212 | return -EINVAL; | ||
213 | } | ||
214 | |||
215 | if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) { | ||
216 | dev_err(dev, "invalid platform data supplied\n"); | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | |||
220 | /* allocate and initialse our state */ | ||
221 | |||
222 | ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL); | ||
223 | if (ili == NULL) { | ||
224 | dev_err(dev, "no memory for device\n"); | ||
225 | return -ENOMEM; | ||
226 | } | ||
227 | |||
228 | ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1); | ||
229 | |||
230 | ili->dev = dev; | ||
231 | ili->client = client; | ||
232 | ili->power = FB_BLANK_POWERDOWN; | ||
233 | ili->platdata = cfg; | ||
234 | |||
235 | dev_set_drvdata(&spi->dev, ili); | ||
236 | |||
237 | ili9320_setup_spi(ili, spi); | ||
238 | |||
239 | lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops); | ||
240 | if (IS_ERR(lcd)) { | ||
241 | dev_err(dev, "failed to register lcd device\n"); | ||
242 | ret = PTR_ERR(lcd); | ||
243 | goto err_free; | ||
244 | } | ||
245 | |||
246 | ili->lcd = lcd; | ||
247 | |||
248 | dev_info(dev, "initialising %s\n", client->name); | ||
249 | |||
250 | ret = ili9320_power(ili, FB_BLANK_UNBLANK); | ||
251 | if (ret != 0) { | ||
252 | dev_err(dev, "failed to set lcd power state\n"); | ||
253 | goto err_unregister; | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | |||
258 | err_unregister: | ||
259 | lcd_device_unregister(lcd); | ||
260 | |||
261 | err_free: | ||
262 | kfree(ili); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | EXPORT_SYMBOL_GPL(ili9320_probe_spi); | ||
268 | |||
269 | int __devexit ili9320_remove(struct ili9320 *ili) | ||
270 | { | ||
271 | ili9320_power(ili, FB_BLANK_POWERDOWN); | ||
272 | |||
273 | lcd_device_unregister(ili->lcd); | ||
274 | kfree(ili); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | EXPORT_SYMBOL_GPL(ili9320_remove); | ||
280 | |||
281 | #ifdef CONFIG_PM | ||
282 | int ili9320_suspend(struct ili9320 *lcd, pm_message_t state) | ||
283 | { | ||
284 | int ret; | ||
285 | |||
286 | dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event); | ||
287 | |||
288 | if (state.event == PM_EVENT_SUSPEND) { | ||
289 | ret = ili9320_power(lcd, FB_BLANK_POWERDOWN); | ||
290 | |||
291 | if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) { | ||
292 | ili9320_write(lcd, ILI9320_POWER1, lcd->power1 | | ||
293 | ILI9320_POWER1_SLP | | ||
294 | ILI9320_POWER1_DSTB); | ||
295 | lcd->initialised = 0; | ||
296 | } | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | EXPORT_SYMBOL_GPL(ili9320_suspend); | ||
305 | |||
306 | int ili9320_resume(struct ili9320 *lcd) | ||
307 | { | ||
308 | dev_info(lcd->dev, "resuming from power state %d\n", lcd->power); | ||
309 | |||
310 | if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) { | ||
311 | ili9320_write(lcd, ILI9320_POWER1, 0x00); | ||
312 | } | ||
313 | |||
314 | return ili9320_power(lcd, FB_BLANK_UNBLANK); | ||
315 | } | ||
316 | |||
317 | EXPORT_SYMBOL_GPL(ili9320_resume); | ||
318 | #endif | ||
319 | |||
320 | /* Power down all displays on reboot, poweroff or halt */ | ||
321 | void ili9320_shutdown(struct ili9320 *lcd) | ||
322 | { | ||
323 | ili9320_power(lcd, FB_BLANK_POWERDOWN); | ||
324 | } | ||
325 | |||
326 | EXPORT_SYMBOL_GPL(ili9320_shutdown); | ||
327 | |||
328 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); | ||
329 | MODULE_DESCRIPTION("ILI9320 LCD Driver"); | ||
330 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h new file mode 100644 index 000000000000..e388eca7cac5 --- /dev/null +++ b/drivers/video/backlight/ili9320.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* drivers/video/backlight/ili9320.h | ||
2 | * | ||
3 | * ILI9320 LCD controller driver core. | ||
4 | * | ||
5 | * Copyright 2007 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * | ||
8 | * http://armlinux.simtec.co.uk/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* Holder for register and value pairs. */ | ||
16 | struct ili9320_reg { | ||
17 | unsigned short address; | ||
18 | unsigned short value; | ||
19 | }; | ||
20 | |||
21 | struct ili9320; | ||
22 | |||
23 | struct ili9320_client { | ||
24 | const char *name; | ||
25 | int (*init)(struct ili9320 *ili, struct ili9320_platdata *cfg); | ||
26 | |||
27 | }; | ||
28 | /* Device attached via an SPI bus. */ | ||
29 | struct ili9320_spi { | ||
30 | struct spi_device *dev; | ||
31 | struct spi_message message; | ||
32 | struct spi_transfer xfer[2]; | ||
33 | |||
34 | unsigned char id; | ||
35 | unsigned char buffer_addr[4]; | ||
36 | unsigned char buffer_data[4]; | ||
37 | }; | ||
38 | |||
39 | /* ILI9320 device state. */ | ||
40 | struct ili9320 { | ||
41 | union { | ||
42 | struct ili9320_spi spi; /* SPI attachged device. */ | ||
43 | } access; /* Register access method. */ | ||
44 | |||
45 | struct device *dev; | ||
46 | struct lcd_device *lcd; /* LCD device we created. */ | ||
47 | struct ili9320_client *client; | ||
48 | struct ili9320_platdata *platdata; | ||
49 | |||
50 | int power; /* current power state. */ | ||
51 | int initialised; | ||
52 | |||
53 | unsigned short display1; | ||
54 | unsigned short power1; | ||
55 | |||
56 | int (*write)(struct ili9320 *ili, unsigned int reg, unsigned int val); | ||
57 | }; | ||
58 | |||
59 | |||
60 | /* ILI9320 register access routines */ | ||
61 | |||
62 | extern int ili9320_write(struct ili9320 *ili, | ||
63 | unsigned int reg, unsigned int value); | ||
64 | |||
65 | extern int ili9320_write_regs(struct ili9320 *ili, | ||
66 | struct ili9320_reg *values, | ||
67 | int nr_values); | ||
68 | |||
69 | /* Device probe */ | ||
70 | |||
71 | extern int ili9320_probe_spi(struct spi_device *spi, | ||
72 | struct ili9320_client *cli); | ||
73 | |||
74 | extern int ili9320_remove(struct ili9320 *lcd); | ||
75 | extern void ili9320_shutdown(struct ili9320 *lcd); | ||
76 | |||
77 | /* PM */ | ||
78 | |||
79 | extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state); | ||
80 | extern int ili9320_resume(struct ili9320 *lcd); | ||
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 299fd318dd45..b15b2b84a6f7 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
@@ -33,7 +33,7 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
33 | ld = container_of(self, struct lcd_device, fb_notif); | 33 | ld = container_of(self, struct lcd_device, fb_notif); |
34 | mutex_lock(&ld->ops_lock); | 34 | mutex_lock(&ld->ops_lock); |
35 | if (ld->ops) | 35 | if (ld->ops) |
36 | if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info)) | 36 | if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) |
37 | ld->ops->set_power(ld, *(int *)evdata->data); | 37 | ld->ops->set_power(ld, *(int *)evdata->data); |
38 | mutex_unlock(&ld->ops_lock); | 38 | mutex_unlock(&ld->ops_lock); |
39 | return 0; | 39 | return 0; |
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c new file mode 100644 index 000000000000..385cba40ea87 --- /dev/null +++ b/drivers/video/backlight/mbp_nvidia_bl.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Backlight Driver for Nvidia 8600 in Macbook Pro | ||
3 | * | ||
4 | * Copyright (c) Red Hat <mjg@redhat.com> | ||
5 | * Based on code from Pommed: | ||
6 | * Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch> | ||
7 | * Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org> | ||
8 | * Copyright (C) 2007 Julien BLACHE <jb@jblache.org> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This driver triggers SMIs which cause the firmware to change the | ||
15 | * backlight brightness. This is icky in many ways, but it's impractical to | ||
16 | * get at the firmware code in order to figure out what it's actually doing. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/backlight.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/dmi.h> | ||
26 | #include <linux/io.h> | ||
27 | |||
28 | static struct backlight_device *mbp_backlight_device; | ||
29 | |||
30 | static struct dmi_system_id __initdata mbp_device_table[] = { | ||
31 | { | ||
32 | .ident = "3,1", | ||
33 | .matches = { | ||
34 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
35 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), | ||
36 | }, | ||
37 | }, | ||
38 | { | ||
39 | .ident = "3,2", | ||
40 | .matches = { | ||
41 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
42 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"), | ||
43 | }, | ||
44 | }, | ||
45 | { | ||
46 | .ident = "4,1", | ||
47 | .matches = { | ||
48 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
49 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"), | ||
50 | }, | ||
51 | }, | ||
52 | { } | ||
53 | }; | ||
54 | |||
55 | static int mbp_send_intensity(struct backlight_device *bd) | ||
56 | { | ||
57 | int intensity = bd->props.brightness; | ||
58 | |||
59 | outb(0x04 | (intensity << 4), 0xb3); | ||
60 | outb(0xbf, 0xb2); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int mbp_get_intensity(struct backlight_device *bd) | ||
66 | { | ||
67 | outb(0x03, 0xb3); | ||
68 | outb(0xbf, 0xb2); | ||
69 | return inb(0xb3) >> 4; | ||
70 | } | ||
71 | |||
72 | static struct backlight_ops mbp_ops = { | ||
73 | .get_brightness = mbp_get_intensity, | ||
74 | .update_status = mbp_send_intensity, | ||
75 | }; | ||
76 | |||
77 | static int __init mbp_init(void) | ||
78 | { | ||
79 | if (!dmi_check_system(mbp_device_table)) | ||
80 | return -ENODEV; | ||
81 | |||
82 | if (!request_region(0xb2, 2, "Macbook Pro backlight")) | ||
83 | return -ENXIO; | ||
84 | |||
85 | mbp_backlight_device = backlight_device_register("mbp_backlight", | ||
86 | NULL, NULL, | ||
87 | &mbp_ops); | ||
88 | if (IS_ERR(mbp_backlight_device)) { | ||
89 | release_region(0xb2, 2); | ||
90 | return PTR_ERR(mbp_backlight_device); | ||
91 | } | ||
92 | |||
93 | mbp_backlight_device->props.max_brightness = 15; | ||
94 | mbp_backlight_device->props.brightness = | ||
95 | mbp_get_intensity(mbp_backlight_device); | ||
96 | backlight_update_status(mbp_backlight_device); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static void __exit mbp_exit(void) | ||
102 | { | ||
103 | backlight_device_unregister(mbp_backlight_device); | ||
104 | |||
105 | release_region(0xb2, 2); | ||
106 | } | ||
107 | |||
108 | module_init(mbp_init); | ||
109 | module_exit(mbp_exit); | ||
110 | |||
111 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); | ||
112 | MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver"); | ||
113 | MODULE_LICENSE("GPL"); | ||
114 | MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1"); | ||
115 | MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2"); | ||
116 | MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1"); | ||
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 891875d53a49..cbad67e89826 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include <linux/fb.h> | 25 | #include <linux/fb.h> |
26 | #include <linux/backlight.h> | 26 | #include <linux/backlight.h> |
27 | 27 | ||
28 | #include <asm/arch/hardware.h> | 28 | #include <mach/hardware.h> |
29 | #include <asm/arch/board.h> | 29 | #include <mach/board.h> |
30 | #include <asm/arch/mux.h> | 30 | #include <mach/mux.h> |
31 | 31 | ||
32 | #define OMAPBL_MAX_INTENSITY 0xff | 32 | #define OMAPBL_MAX_INTENSITY 0xff |
33 | 33 | ||
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c new file mode 100644 index 000000000000..738694d23889 --- /dev/null +++ b/drivers/video/backlight/platform_lcd.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* drivers/video/backlight/platform_lcd.c | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Generic platform-device LCD power control interface. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/fb.h> | ||
17 | #include <linux/backlight.h> | ||
18 | #include <linux/lcd.h> | ||
19 | |||
20 | #include <video/platform_lcd.h> | ||
21 | |||
22 | struct platform_lcd { | ||
23 | struct device *us; | ||
24 | struct lcd_device *lcd; | ||
25 | struct plat_lcd_data *pdata; | ||
26 | |||
27 | unsigned int power; | ||
28 | unsigned int suspended : 1; | ||
29 | }; | ||
30 | |||
31 | static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd) | ||
32 | { | ||
33 | return lcd_get_data(lcd); | ||
34 | } | ||
35 | |||
36 | static int platform_lcd_get_power(struct lcd_device *lcd) | ||
37 | { | ||
38 | struct platform_lcd *plcd = to_our_lcd(lcd); | ||
39 | |||
40 | return plcd->power; | ||
41 | } | ||
42 | |||
43 | static int platform_lcd_set_power(struct lcd_device *lcd, int power) | ||
44 | { | ||
45 | struct platform_lcd *plcd = to_our_lcd(lcd); | ||
46 | int lcd_power = 1; | ||
47 | |||
48 | if (power == FB_BLANK_POWERDOWN || plcd->suspended) | ||
49 | lcd_power = 0; | ||
50 | |||
51 | plcd->pdata->set_power(plcd->pdata, lcd_power); | ||
52 | plcd->power = power; | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info) | ||
58 | { | ||
59 | struct platform_lcd *plcd = to_our_lcd(lcd); | ||
60 | struct plat_lcd_data *pdata = plcd->pdata; | ||
61 | |||
62 | if (pdata->match_fb) | ||
63 | return pdata->match_fb(pdata, info); | ||
64 | |||
65 | return plcd->us->parent == info->device; | ||
66 | } | ||
67 | |||
68 | static struct lcd_ops platform_lcd_ops = { | ||
69 | .get_power = platform_lcd_get_power, | ||
70 | .set_power = platform_lcd_set_power, | ||
71 | .check_fb = platform_lcd_match, | ||
72 | }; | ||
73 | |||
74 | static int __devinit platform_lcd_probe(struct platform_device *pdev) | ||
75 | { | ||
76 | struct plat_lcd_data *pdata; | ||
77 | struct platform_lcd *plcd; | ||
78 | struct device *dev = &pdev->dev; | ||
79 | int err; | ||
80 | |||
81 | pdata = pdev->dev.platform_data; | ||
82 | if (!pdata) { | ||
83 | dev_err(dev, "no platform data supplied\n"); | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL); | ||
88 | if (!plcd) { | ||
89 | dev_err(dev, "no memory for state\n"); | ||
90 | return -ENOMEM; | ||
91 | } | ||
92 | |||
93 | plcd->us = dev; | ||
94 | plcd->pdata = pdata; | ||
95 | plcd->lcd = lcd_device_register(dev_name(dev), dev, | ||
96 | plcd, &platform_lcd_ops); | ||
97 | if (IS_ERR(plcd->lcd)) { | ||
98 | dev_err(dev, "cannot register lcd device\n"); | ||
99 | err = PTR_ERR(plcd->lcd); | ||
100 | goto err_mem; | ||
101 | } | ||
102 | |||
103 | platform_set_drvdata(pdev, plcd); | ||
104 | platform_lcd_set_power(plcd->lcd, FB_BLANK_NORMAL); | ||
105 | |||
106 | return 0; | ||
107 | |||
108 | err_mem: | ||
109 | kfree(plcd); | ||
110 | return err; | ||
111 | } | ||
112 | |||
113 | static int __devexit platform_lcd_remove(struct platform_device *pdev) | ||
114 | { | ||
115 | struct platform_lcd *plcd = platform_get_drvdata(pdev); | ||
116 | |||
117 | lcd_device_unregister(plcd->lcd); | ||
118 | kfree(plcd); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | #ifdef CONFIG_PM | ||
124 | static int platform_lcd_suspend(struct platform_device *pdev, pm_message_t st) | ||
125 | { | ||
126 | struct platform_lcd *plcd = platform_get_drvdata(pdev); | ||
127 | |||
128 | plcd->suspended = 1; | ||
129 | platform_lcd_set_power(plcd->lcd, plcd->power); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int platform_lcd_resume(struct platform_device *pdev) | ||
135 | { | ||
136 | struct platform_lcd *plcd = platform_get_drvdata(pdev); | ||
137 | |||
138 | plcd->suspended = 0; | ||
139 | platform_lcd_set_power(plcd->lcd, plcd->power); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | #else | ||
144 | #define platform_lcd_suspend NULL | ||
145 | #define platform_lcd_resume NULL | ||
146 | #endif | ||
147 | |||
148 | static struct platform_driver platform_lcd_driver = { | ||
149 | .driver = { | ||
150 | .name = "platform-lcd", | ||
151 | .owner = THIS_MODULE, | ||
152 | }, | ||
153 | .probe = platform_lcd_probe, | ||
154 | .remove = __devexit_p(platform_lcd_remove), | ||
155 | .suspend = platform_lcd_suspend, | ||
156 | .resume = platform_lcd_resume, | ||
157 | }; | ||
158 | |||
159 | static int __init platform_lcd_init(void) | ||
160 | { | ||
161 | return platform_driver_register(&platform_lcd_driver); | ||
162 | } | ||
163 | |||
164 | static void __exit platform_lcd_cleanup(void) | ||
165 | { | ||
166 | platform_driver_unregister(&platform_lcd_driver); | ||
167 | } | ||
168 | |||
169 | module_init(platform_lcd_init); | ||
170 | module_exit(platform_lcd_cleanup); | ||
171 | |||
172 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); | ||
173 | MODULE_LICENSE("GPL v2"); | ||
174 | MODULE_ALIAS("platform:platform-lcd"); | ||
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 6338d0e2fe07..ea07258565f0 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -68,8 +68,10 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
68 | struct pwm_bl_data *pb; | 68 | struct pwm_bl_data *pb; |
69 | int ret; | 69 | int ret; |
70 | 70 | ||
71 | if (!data) | 71 | if (!data) { |
72 | dev_err(&pdev->dev, "failed to find platform data\n"); | ||
72 | return -EINVAL; | 73 | return -EINVAL; |
74 | } | ||
73 | 75 | ||
74 | if (data->init) { | 76 | if (data->init) { |
75 | ret = data->init(&pdev->dev); | 77 | ret = data->init(&pdev->dev); |
@@ -79,6 +81,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
79 | 81 | ||
80 | pb = kzalloc(sizeof(*pb), GFP_KERNEL); | 82 | pb = kzalloc(sizeof(*pb), GFP_KERNEL); |
81 | if (!pb) { | 83 | if (!pb) { |
84 | dev_err(&pdev->dev, "no memory for state\n"); | ||
82 | ret = -ENOMEM; | 85 | ret = -ENOMEM; |
83 | goto err_alloc; | 86 | goto err_alloc; |
84 | } | 87 | } |
@@ -91,7 +94,8 @@ static int pwm_backlight_probe(struct platform_device *pdev) | |||
91 | dev_err(&pdev->dev, "unable to request PWM for backlight\n"); | 94 | dev_err(&pdev->dev, "unable to request PWM for backlight\n"); |
92 | ret = PTR_ERR(pb->pwm); | 95 | ret = PTR_ERR(pb->pwm); |
93 | goto err_pwm; | 96 | goto err_pwm; |
94 | } | 97 | } else |
98 | dev_dbg(&pdev->dev, "got pwm for backlight\n"); | ||
95 | 99 | ||
96 | bl = backlight_device_register(pdev->name, &pdev->dev, | 100 | bl = backlight_device_register(pdev->name, &pdev->dev, |
97 | pb, &pwm_backlight_ops); | 101 | pb, &pwm_backlight_ops); |
@@ -183,3 +187,5 @@ module_exit(pwm_backlight_exit); | |||
183 | 187 | ||
184 | MODULE_DESCRIPTION("PWM based Backlight Driver"); | 188 | MODULE_DESCRIPTION("PWM based Backlight Driver"); |
185 | MODULE_LICENSE("GPL"); | 189 | MODULE_LICENSE("GPL"); |
190 | MODULE_ALIAS("platform:pwm-backlight"); | ||
191 | |||
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c new file mode 100644 index 000000000000..593c7687d54a --- /dev/null +++ b/drivers/video/backlight/vgg2432a4.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* drivers/video/backlight/vgg2432a4.c | ||
2 | * | ||
3 | * VGG2432A4 (ILI9320) LCD controller driver. | ||
4 | * | ||
5 | * Copyright 2007 Simtec Electronics | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * Ben Dooks <ben@simtec.co.uk> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/fb.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/lcd.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <linux/spi/spi.h> | ||
22 | |||
23 | #include <video/ili9320.h> | ||
24 | |||
25 | #include "ili9320.h" | ||
26 | |||
27 | /* Device initialisation sequences */ | ||
28 | |||
29 | static struct ili9320_reg vgg_init1[] = { | ||
30 | { | ||
31 | .address = ILI9320_POWER1, | ||
32 | .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0), | ||
33 | }, { | ||
34 | .address = ILI9320_POWER2, | ||
35 | .value = (ILI9320_POWER2_VC(7) | | ||
36 | ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)), | ||
37 | }, { | ||
38 | .address = ILI9320_POWER3, | ||
39 | .value = ILI9320_POWER3_VRH(0), | ||
40 | }, { | ||
41 | .address = ILI9320_POWER4, | ||
42 | .value = ILI9320_POWER4_VREOUT(0), | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | static struct ili9320_reg vgg_init2[] = { | ||
47 | { | ||
48 | .address = ILI9320_POWER1, | ||
49 | .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE | | ||
50 | ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP), | ||
51 | }, { | ||
52 | .address = ILI9320_POWER2, | ||
53 | .value = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3), | ||
54 | } | ||
55 | }; | ||
56 | |||
57 | static struct ili9320_reg vgg_gamma[] = { | ||
58 | { | ||
59 | .address = ILI9320_GAMMA1, | ||
60 | .value = 0x0000, | ||
61 | }, { | ||
62 | .address = ILI9320_GAMMA2, | ||
63 | .value = 0x0505, | ||
64 | }, { | ||
65 | .address = ILI9320_GAMMA3, | ||
66 | .value = 0x0004, | ||
67 | }, { | ||
68 | .address = ILI9320_GAMMA4, | ||
69 | .value = 0x0006, | ||
70 | }, { | ||
71 | .address = ILI9320_GAMMA5, | ||
72 | .value = 0x0707, | ||
73 | }, { | ||
74 | .address = ILI9320_GAMMA6, | ||
75 | .value = 0x0105, | ||
76 | }, { | ||
77 | .address = ILI9320_GAMMA7, | ||
78 | .value = 0x0002, | ||
79 | }, { | ||
80 | .address = ILI9320_GAMMA8, | ||
81 | .value = 0x0707, | ||
82 | }, { | ||
83 | .address = ILI9320_GAMMA9, | ||
84 | .value = 0x0704, | ||
85 | }, { | ||
86 | .address = ILI9320_GAMMA10, | ||
87 | .value = 0x807, | ||
88 | } | ||
89 | |||
90 | }; | ||
91 | |||
92 | static struct ili9320_reg vgg_init0[] = { | ||
93 | [0] = { | ||
94 | /* set direction and scan mode gate */ | ||
95 | .address = ILI9320_DRIVER, | ||
96 | .value = ILI9320_DRIVER_SS, | ||
97 | }, { | ||
98 | .address = ILI9320_DRIVEWAVE, | ||
99 | .value = (ILI9320_DRIVEWAVE_MUSTSET | | ||
100 | ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC), | ||
101 | }, { | ||
102 | .address = ILI9320_ENTRYMODE, | ||
103 | .value = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR, | ||
104 | }, { | ||
105 | .address = ILI9320_RESIZING, | ||
106 | .value = 0x0, | ||
107 | }, | ||
108 | }; | ||
109 | |||
110 | |||
111 | static int vgg2432a4_lcd_init(struct ili9320 *lcd, | ||
112 | struct ili9320_platdata *cfg) | ||
113 | { | ||
114 | unsigned int addr; | ||
115 | int ret; | ||
116 | |||
117 | /* Set VCore before anything else (VGG243237-6UFLWA) */ | ||
118 | ret = ili9320_write(lcd, 0x00e5, 0x8000); | ||
119 | if (ret) | ||
120 | goto err_initial; | ||
121 | |||
122 | /* Start the oscillator up before we can do anything else. */ | ||
123 | ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC); | ||
124 | if (ret) | ||
125 | goto err_initial; | ||
126 | |||
127 | /* must wait at-lesat 10ms after starting */ | ||
128 | mdelay(15); | ||
129 | |||
130 | ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0)); | ||
131 | if (ret != 0) | ||
132 | goto err_initial; | ||
133 | |||
134 | ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2); | ||
135 | ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3); | ||
136 | ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4); | ||
137 | |||
138 | ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1); | ||
139 | ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0); | ||
140 | ili9320_write(lcd, ILI9320_RGB_IF2, ILI9320_RGBIF2_DPL); | ||
141 | |||
142 | ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1)); | ||
143 | if (ret != 0) | ||
144 | goto err_vgg; | ||
145 | |||
146 | mdelay(300); | ||
147 | |||
148 | ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2)); | ||
149 | if (ret != 0) | ||
150 | goto err_vgg2; | ||
151 | |||
152 | mdelay(100); | ||
153 | |||
154 | ili9320_write(lcd, ILI9320_POWER3, 0x13c); | ||
155 | |||
156 | mdelay(100); | ||
157 | |||
158 | ili9320_write(lcd, ILI9320_POWER4, 0x1c00); | ||
159 | ili9320_write(lcd, ILI9320_POWER7, 0x000e); | ||
160 | |||
161 | mdelay(100); | ||
162 | |||
163 | ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00); | ||
164 | ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00); | ||
165 | |||
166 | ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma)); | ||
167 | if (ret != 0) | ||
168 | goto err_vgg3; | ||
169 | |||
170 | ili9320_write(lcd, ILI9320_HORIZ_START, 0x0); | ||
171 | ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1); | ||
172 | ili9320_write(lcd, ILI9320_VERT_START, 0x0); | ||
173 | ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1); | ||
174 | |||
175 | ili9320_write(lcd, ILI9320_DRIVER2, | ||
176 | ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D)); | ||
177 | |||
178 | ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1); | ||
179 | ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00); | ||
180 | |||
181 | for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END; | ||
182 | addr++) { | ||
183 | ili9320_write(lcd, addr, 0x0); | ||
184 | } | ||
185 | |||
186 | ili9320_write(lcd, ILI9320_INTERFACE1, 0x10); | ||
187 | ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2); | ||
188 | ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3); | ||
189 | ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4); | ||
190 | ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5); | ||
191 | ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6); | ||
192 | |||
193 | lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE | | ||
194 | ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE | | ||
195 | 0x40); | ||
196 | |||
197 | ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1); | ||
198 | |||
199 | return 0; | ||
200 | |||
201 | err_vgg3: | ||
202 | err_vgg2: | ||
203 | err_vgg: | ||
204 | err_initial: | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | #ifdef CONFIG_PM | ||
209 | static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state) | ||
210 | { | ||
211 | return ili9320_suspend(dev_get_drvdata(&spi->dev), state); | ||
212 | } | ||
213 | |||
214 | static int vgg2432a4_resume(struct spi_device *spi) | ||
215 | { | ||
216 | return ili9320_resume(dev_get_drvdata(&spi->dev)); | ||
217 | } | ||
218 | #else | ||
219 | #define vgg2432a4_suspend NULL | ||
220 | #define vgg2432a4_resume NULL | ||
221 | #endif | ||
222 | |||
223 | static struct ili9320_client vgg2432a4_client = { | ||
224 | .name = "VGG2432A4", | ||
225 | .init = vgg2432a4_lcd_init, | ||
226 | }; | ||
227 | |||
228 | /* Device probe */ | ||
229 | |||
230 | static int __devinit vgg2432a4_probe(struct spi_device *spi) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | ret = ili9320_probe_spi(spi, &vgg2432a4_client); | ||
235 | if (ret != 0) { | ||
236 | dev_err(&spi->dev, "failed to initialise ili9320\n"); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int __devexit vgg2432a4_remove(struct spi_device *spi) | ||
244 | { | ||
245 | return ili9320_remove(dev_get_drvdata(&spi->dev)); | ||
246 | } | ||
247 | |||
248 | static void vgg2432a4_shutdown(struct spi_device *spi) | ||
249 | { | ||
250 | ili9320_shutdown(dev_get_drvdata(&spi->dev)); | ||
251 | } | ||
252 | |||
253 | static struct spi_driver vgg2432a4_driver = { | ||
254 | .driver = { | ||
255 | .name = "VGG2432A4", | ||
256 | .owner = THIS_MODULE, | ||
257 | }, | ||
258 | .probe = vgg2432a4_probe, | ||
259 | .remove = __devexit_p(vgg2432a4_remove), | ||
260 | .shutdown = vgg2432a4_shutdown, | ||
261 | .suspend = vgg2432a4_suspend, | ||
262 | .resume = vgg2432a4_resume, | ||
263 | }; | ||
264 | |||
265 | /* Device driver initialisation */ | ||
266 | |||
267 | static int __init vgg2432a4_init(void) | ||
268 | { | ||
269 | return spi_register_driver(&vgg2432a4_driver); | ||
270 | } | ||
271 | |||
272 | static void __exit vgg2432a4_exit(void) | ||
273 | { | ||
274 | spi_unregister_driver(&vgg2432a4_driver); | ||
275 | } | ||
276 | |||
277 | module_init(vgg2432a4_init); | ||
278 | module_exit(vgg2432a4_exit); | ||
279 | |||
280 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); | ||
281 | MODULE_DESCRIPTION("VGG2432A4 LCD Driver"); | ||
282 | MODULE_LICENSE("GPL v2"); | ||
283 | |||
284 | |||
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 49834a67a623..7644ed249564 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -58,7 +58,7 @@ | |||
58 | #include <asm/gpio.h> | 58 | #include <asm/gpio.h> |
59 | #include <asm/portmux.h> | 59 | #include <asm/portmux.h> |
60 | 60 | ||
61 | #include <asm/mach/bf54x-lq043.h> | 61 | #include <mach/bf54x-lq043.h> |
62 | 62 | ||
63 | #define NO_BL_SUPPORT | 63 | #define NO_BL_SUPPORT |
64 | 64 | ||
@@ -478,7 +478,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast) | |||
478 | return 0; | 478 | return 0; |
479 | } | 479 | } |
480 | 480 | ||
481 | static int bfin_lcd_check_fb(struct fb_info *fi) | 481 | static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi) |
482 | { | 482 | { |
483 | if (!fi || (fi == &bfin_bf54x_fb)) | 483 | if (!fi || (fi == &bfin_bf54x_fb)) |
484 | return 1; | 484 | return 1; |
@@ -733,7 +733,6 @@ static int bfin_bf54x_remove(struct platform_device *pdev) | |||
733 | static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state) | 733 | static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state) |
734 | { | 734 | { |
735 | struct fb_info *fbinfo = platform_get_drvdata(pdev); | 735 | struct fb_info *fbinfo = platform_get_drvdata(pdev); |
736 | struct bfin_bf54xfb_info *info = fbinfo->par; | ||
737 | 736 | ||
738 | bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); | 737 | bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); |
739 | disable_dma(CH_EPPI0); | 738 | disable_dma(CH_EPPI0); |
@@ -747,8 +746,18 @@ static int bfin_bf54x_resume(struct platform_device *pdev) | |||
747 | struct fb_info *fbinfo = platform_get_drvdata(pdev); | 746 | struct fb_info *fbinfo = platform_get_drvdata(pdev); |
748 | struct bfin_bf54xfb_info *info = fbinfo->par; | 747 | struct bfin_bf54xfb_info *info = fbinfo->par; |
749 | 748 | ||
750 | enable_dma(CH_EPPI0); | 749 | if (info->lq043_open_cnt) { |
751 | bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); | 750 | |
751 | bfin_write_EPPI0_CONTROL(0); | ||
752 | SSYNC(); | ||
753 | |||
754 | config_dma(info); | ||
755 | config_ppi(info); | ||
756 | |||
757 | /* start dma */ | ||
758 | enable_dma(CH_EPPI0); | ||
759 | bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); | ||
760 | } | ||
752 | 761 | ||
753 | return 0; | 762 | return 0; |
754 | } | 763 | } |
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 135d6dd7e672..7d1b819e501c 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c | |||
@@ -396,7 +396,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast) | |||
396 | return 0; | 396 | return 0; |
397 | } | 397 | } |
398 | 398 | ||
399 | static int bfin_lcd_check_fb(struct fb_info *fi) | 399 | static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi) |
400 | { | 400 | { |
401 | if (!fi || (fi == &bfin_t350mcqb_fb)) | 401 | if (!fi || (fi == &bfin_t350mcqb_fb)) |
402 | return 1; | 402 | return 1; |
diff --git a/drivers/video/c2p.c b/drivers/video/c2p.c index 5c30bbd33054..376bc07ff952 100644 --- a/drivers/video/c2p.c +++ b/drivers/video/c2p.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * for more details. | 12 | * for more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | ||
15 | #include <linux/string.h> | 16 | #include <linux/string.h> |
16 | #include "c2p.h" | 17 | #include "c2p.h" |
17 | 18 | ||
@@ -226,4 +227,6 @@ void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height, | |||
226 | dst += dst_nextline; | 227 | dst += dst_nextline; |
227 | } | 228 | } |
228 | } | 229 | } |
230 | EXPORT_SYMBOL_GPL(c2p); | ||
229 | 231 | ||
232 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c new file mode 100644 index 000000000000..e15bb447440a --- /dev/null +++ b/drivers/video/carminefb.c | |||
@@ -0,0 +1,790 @@ | |||
1 | /* | ||
2 | * Frame buffer driver for the Carmine GPU. | ||
3 | * | ||
4 | * The driver configures the GPU as follows | ||
5 | * - FB0 is display 0 with unique memory area | ||
6 | * - FB1 is display 1 with unique memory area | ||
7 | * - both display use 32 bit colors | ||
8 | */ | ||
9 | #include <linux/delay.h> | ||
10 | #include <linux/errno.h> | ||
11 | #include <linux/fb.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/pci.h> | ||
14 | |||
15 | #include "carminefb.h" | ||
16 | #include "carminefb_regs.h" | ||
17 | |||
18 | #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) | ||
19 | #error "The endianness of the target host has not been defined." | ||
20 | #endif | ||
21 | |||
22 | /* | ||
23 | * The initial video mode can be supplied via two different ways: | ||
24 | * - as a string that is passed to fb_find_mode() (module option fb_mode_str) | ||
25 | * - as an integer that picks the video mode from carmine_modedb[] (module | ||
26 | * option fb_mode) | ||
27 | * | ||
28 | * If nothing is used than the initial video mode will be the | ||
29 | * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[]. | ||
30 | */ | ||
31 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 | ||
32 | |||
33 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; | ||
34 | module_param(fb_mode, uint, 444); | ||
35 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); | ||
36 | |||
37 | static char *fb_mode_str; | ||
38 | module_param(fb_mode_str, charp, 444); | ||
39 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | ||
40 | |||
41 | /* | ||
42 | * Carminefb displays: | ||
43 | * 0b000 None | ||
44 | * 0b001 Display 0 | ||
45 | * 0b010 Display 1 | ||
46 | */ | ||
47 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; | ||
48 | module_param(fb_displays, int, 444); | ||
49 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); | ||
50 | |||
51 | struct carmine_hw { | ||
52 | void __iomem *v_regs; | ||
53 | void __iomem *screen_mem; | ||
54 | struct fb_info *fb[MAX_DISPLAY]; | ||
55 | }; | ||
56 | |||
57 | struct carmine_resolution { | ||
58 | u32 htp; | ||
59 | u32 hsp; | ||
60 | u32 hsw; | ||
61 | u32 hdp; | ||
62 | u32 vtr; | ||
63 | u32 vsp; | ||
64 | u32 vsw; | ||
65 | u32 vdp; | ||
66 | u32 disp_mode; | ||
67 | }; | ||
68 | |||
69 | struct carmine_fb { | ||
70 | void __iomem *display_reg; | ||
71 | void __iomem *screen_base; | ||
72 | u32 smem_offset; | ||
73 | u32 cur_mode; | ||
74 | u32 new_mode; | ||
75 | struct carmine_resolution *res; | ||
76 | u32 pseudo_palette[16]; | ||
77 | }; | ||
78 | |||
79 | static struct fb_fix_screeninfo carminefb_fix __devinitdata = { | ||
80 | .id = "Carmine", | ||
81 | .type = FB_TYPE_PACKED_PIXELS, | ||
82 | .visual = FB_VISUAL_TRUECOLOR, | ||
83 | .accel = FB_ACCEL_NONE, | ||
84 | }; | ||
85 | |||
86 | static const struct fb_videomode carmine_modedb[] = { | ||
87 | { | ||
88 | .name = "640x480", | ||
89 | .xres = 640, | ||
90 | .yres = 480, | ||
91 | }, { | ||
92 | .name = "800x600", | ||
93 | .xres = 800, | ||
94 | .yres = 600, | ||
95 | }, | ||
96 | }; | ||
97 | |||
98 | static struct carmine_resolution car_modes[] = { | ||
99 | { | ||
100 | /* 640x480 */ | ||
101 | .htp = 800, | ||
102 | .hsp = 672, | ||
103 | .hsw = 96, | ||
104 | .hdp = 640, | ||
105 | .vtr = 525, | ||
106 | .vsp = 490, | ||
107 | .vsw = 2, | ||
108 | .vdp = 480, | ||
109 | .disp_mode = 0x1400, | ||
110 | }, | ||
111 | { | ||
112 | /* 800x600 */ | ||
113 | .htp = 1060, | ||
114 | .hsp = 864, | ||
115 | .hsw = 72, | ||
116 | .hdp = 800, | ||
117 | .vtr = 628, | ||
118 | .vsp = 601, | ||
119 | .vsw = 2, | ||
120 | .vdp = 600, | ||
121 | .disp_mode = 0x0d00, | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | static int carmine_find_mode(const struct fb_var_screeninfo *var) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | for (i = 0; i < ARRAY_SIZE(car_modes); i++) | ||
130 | if (car_modes[i].hdp == var->xres && | ||
131 | car_modes[i].vdp == var->yres) | ||
132 | return i; | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | static void c_set_disp_reg(const struct carmine_fb *par, | ||
137 | u32 offset, u32 val) | ||
138 | { | ||
139 | writel(val, par->display_reg + offset); | ||
140 | } | ||
141 | |||
142 | static u32 c_get_disp_reg(const struct carmine_fb *par, | ||
143 | u32 offset) | ||
144 | { | ||
145 | return readl(par->display_reg + offset); | ||
146 | } | ||
147 | |||
148 | static void c_set_hw_reg(const struct carmine_hw *hw, | ||
149 | u32 offset, u32 val) | ||
150 | { | ||
151 | writel(val, hw->v_regs + offset); | ||
152 | } | ||
153 | |||
154 | static u32 c_get_hw_reg(const struct carmine_hw *hw, | ||
155 | u32 offset) | ||
156 | { | ||
157 | return readl(hw->v_regs + offset); | ||
158 | } | ||
159 | |||
160 | static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
161 | unsigned blue, unsigned transp, struct fb_info *info) | ||
162 | { | ||
163 | if (regno >= 16) | ||
164 | return 1; | ||
165 | |||
166 | red >>= 8; | ||
167 | green >>= 8; | ||
168 | blue >>= 8; | ||
169 | transp >>= 8; | ||
170 | |||
171 | ((u32 *)info->pseudo_palette)[regno] = be32_to_cpu(transp << 24 | | ||
172 | red << 0 | green << 8 | blue << 16); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int carmine_check_var(struct fb_var_screeninfo *var, | ||
177 | struct fb_info *info) | ||
178 | { | ||
179 | int ret; | ||
180 | |||
181 | ret = carmine_find_mode(var); | ||
182 | if (ret < 0) | ||
183 | return ret; | ||
184 | |||
185 | if (var->grayscale || var->rotate || var->nonstd) | ||
186 | return -EINVAL; | ||
187 | |||
188 | var->xres_virtual = var->xres; | ||
189 | var->yres_virtual = var->yres; | ||
190 | |||
191 | var->bits_per_pixel = 32; | ||
192 | |||
193 | #ifdef __BIG_ENDIAN | ||
194 | var->transp.offset = 24; | ||
195 | var->red.offset = 0; | ||
196 | var->green.offset = 8; | ||
197 | var->blue.offset = 16; | ||
198 | #else | ||
199 | var->transp.offset = 24; | ||
200 | var->red.offset = 16; | ||
201 | var->green.offset = 8; | ||
202 | var->blue.offset = 0; | ||
203 | #endif | ||
204 | |||
205 | var->red.length = 8; | ||
206 | var->green.length = 8; | ||
207 | var->blue.length = 8; | ||
208 | var->transp.length = 8; | ||
209 | |||
210 | var->red.msb_right = 0; | ||
211 | var->green.msb_right = 0; | ||
212 | var->blue.msb_right = 0; | ||
213 | var->transp.msb_right = 0; | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static void carmine_init_display_param(struct carmine_fb *par) | ||
218 | { | ||
219 | u32 width; | ||
220 | u32 height; | ||
221 | u32 param; | ||
222 | u32 window_size; | ||
223 | u32 soffset = par->smem_offset; | ||
224 | |||
225 | c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0); | ||
226 | c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0); | ||
227 | c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE, | ||
228 | CARMINE_CURSOR0_PRIORITY_MASK | | ||
229 | CARMINE_CURSOR1_PRIORITY_MASK | | ||
230 | CARMINE_CURSOR_CUTZ_MASK); | ||
231 | |||
232 | /* Set default cursor position */ | ||
233 | c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0); | ||
234 | c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0); | ||
235 | |||
236 | /* Set default display mode */ | ||
237 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE | | ||
238 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
239 | c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE, | ||
240 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
241 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE | | ||
242 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
243 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE | | ||
244 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
245 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE | | ||
246 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
247 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE | | ||
248 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
249 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE | | ||
250 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
251 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE | | ||
252 | CARMINE_EXT_CMODE_DIRECT24_RGBA); | ||
253 | |||
254 | /* Set default frame size to layer mode register */ | ||
255 | width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT; | ||
256 | width = width << CARMINE_DISP_WIDTH_SHIFT; | ||
257 | |||
258 | height = par->res->vdp - 1; | ||
259 | param = width | height; | ||
260 | |||
261 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param); | ||
262 | c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width); | ||
263 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param); | ||
264 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param); | ||
265 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param); | ||
266 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param); | ||
267 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param); | ||
268 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param); | ||
269 | |||
270 | /* Set default pos and size */ | ||
271 | window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT; | ||
272 | window_size |= par->res->hdp; | ||
273 | |||
274 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0); | ||
275 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size); | ||
276 | c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0); | ||
277 | c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size); | ||
278 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0); | ||
279 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size); | ||
280 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0); | ||
281 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size); | ||
282 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0); | ||
283 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size); | ||
284 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0); | ||
285 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size); | ||
286 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0); | ||
287 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size); | ||
288 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0); | ||
289 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size); | ||
290 | |||
291 | /* Set default origin address */ | ||
292 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset); | ||
293 | c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset); | ||
294 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset); | ||
295 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset); | ||
296 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset); | ||
297 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset); | ||
298 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset); | ||
299 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset); | ||
300 | |||
301 | /* Set default display address */ | ||
302 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset); | ||
303 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset); | ||
304 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset); | ||
305 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset); | ||
306 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset); | ||
307 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset); | ||
308 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset); | ||
309 | |||
310 | /* Set default display position */ | ||
311 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0); | ||
312 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0); | ||
313 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0); | ||
314 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0); | ||
315 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0); | ||
316 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0); | ||
317 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0); | ||
318 | |||
319 | /* Set default blend mode */ | ||
320 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0); | ||
321 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0); | ||
322 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0); | ||
323 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0); | ||
324 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0); | ||
325 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0); | ||
326 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0); | ||
327 | c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0); | ||
328 | |||
329 | /* default transparency mode */ | ||
330 | c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0); | ||
331 | c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0); | ||
332 | c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0); | ||
333 | c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0); | ||
334 | c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0); | ||
335 | c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0); | ||
336 | c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0); | ||
337 | c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0); | ||
338 | |||
339 | /* Set default read skip parameter */ | ||
340 | c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0); | ||
341 | c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0); | ||
342 | c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0); | ||
343 | c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0); | ||
344 | c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0); | ||
345 | c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0); | ||
346 | c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0); | ||
347 | |||
348 | c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0); | ||
349 | c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0); | ||
350 | c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0); | ||
351 | c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0); | ||
352 | c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0); | ||
353 | c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0); | ||
354 | c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0); | ||
355 | |||
356 | c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0); | ||
357 | c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0); | ||
358 | c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0); | ||
359 | c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0); | ||
360 | c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0); | ||
361 | c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0); | ||
362 | c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0); | ||
363 | } | ||
364 | |||
365 | static void set_display_parameters(struct carmine_fb *par) | ||
366 | { | ||
367 | u32 mode; | ||
368 | u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw; | ||
369 | |||
370 | /* | ||
371 | * display timing. Parameters are decreased by one because hardware | ||
372 | * spec is 0 to (n - 1) | ||
373 | * */ | ||
374 | hdp = par->res->hdp - 1; | ||
375 | vdp = par->res->vdp - 1; | ||
376 | htp = par->res->htp - 1; | ||
377 | hsp = par->res->hsp - 1; | ||
378 | hsw = par->res->hsw - 1; | ||
379 | vtr = par->res->vtr - 1; | ||
380 | vsp = par->res->vsp - 1; | ||
381 | vsw = par->res->vsw - 1; | ||
382 | |||
383 | c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL, | ||
384 | htp << CARMINE_DISP_HTP_SHIFT); | ||
385 | c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD, | ||
386 | (hdp << CARMINE_DISP_HDB_SHIFT) | hdp); | ||
387 | c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS, | ||
388 | (vsw << CARMINE_DISP_VSW_SHIFT) | | ||
389 | (hsw << CARMINE_DISP_HSW_SHIFT) | | ||
390 | (hsp)); | ||
391 | c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL, | ||
392 | vtr << CARMINE_DISP_VTR_SHIFT); | ||
393 | c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS, | ||
394 | (vdp << CARMINE_DISP_VDP_SHIFT) | vsp); | ||
395 | |||
396 | /* clock */ | ||
397 | mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1); | ||
398 | mode = (mode & ~CARMINE_DISP_DCM_MASK) | | ||
399 | (par->res->disp_mode & CARMINE_DISP_DCM_MASK); | ||
400 | /* enable video output and layer 0 */ | ||
401 | mode |= CARMINE_DEN | CARMINE_L0E; | ||
402 | c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode); | ||
403 | } | ||
404 | |||
405 | static int carmine_set_par(struct fb_info *info) | ||
406 | { | ||
407 | struct carmine_fb *par = info->par; | ||
408 | int ret; | ||
409 | |||
410 | ret = carmine_find_mode(&info->var); | ||
411 | if (ret < 0) | ||
412 | return ret; | ||
413 | |||
414 | par->new_mode = ret; | ||
415 | if (par->cur_mode != par->new_mode) { | ||
416 | |||
417 | par->cur_mode = par->new_mode; | ||
418 | par->res = &car_modes[par->new_mode]; | ||
419 | |||
420 | carmine_init_display_param(par); | ||
421 | set_display_parameters(par); | ||
422 | } | ||
423 | |||
424 | info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8; | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static int init_hardware(struct carmine_hw *hw) | ||
429 | { | ||
430 | u32 flags; | ||
431 | u32 loops; | ||
432 | u32 ret; | ||
433 | |||
434 | /* Initalize Carmine */ | ||
435 | /* Sets internal clock */ | ||
436 | c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, | ||
437 | CARMINE_DFLT_IP_CLOCK_ENABLE); | ||
438 | |||
439 | /* Video signal output is turned off */ | ||
440 | c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0); | ||
441 | c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0); | ||
442 | |||
443 | /* Software reset */ | ||
444 | c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1); | ||
445 | c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0); | ||
446 | |||
447 | /* I/O mode settings */ | ||
448 | flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 | | ||
449 | CARMINE_DFLT_IP_DCTL_IO_CONT0; | ||
450 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0, | ||
451 | flags); | ||
452 | |||
453 | /* DRAM initial sequence */ | ||
454 | flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD; | ||
455 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, | ||
456 | flags); | ||
457 | |||
458 | flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 | | ||
459 | CARMINE_DFLT_IP_DCTL_EMODE; | ||
460 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE, | ||
461 | flags); | ||
462 | |||
463 | flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 | | ||
464 | CARMINE_DFLT_IP_DCTL_SET_TIME2; | ||
465 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2, | ||
466 | flags); | ||
467 | |||
468 | flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 | | ||
469 | CARMINE_DFLT_IP_DCTL_FIFO_DEPTH; | ||
470 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags); | ||
471 | |||
472 | flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1; | ||
473 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1, | ||
474 | flags); | ||
475 | |||
476 | flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 | | ||
477 | CARMINE_DFLT_IP_DCTL_STATES; | ||
478 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES, | ||
479 | flags); | ||
480 | |||
481 | /* Executes DLL reset */ | ||
482 | if (CARMINE_DCTL_DLL_RESET) { | ||
483 | for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) { | ||
484 | |||
485 | ret = c_get_hw_reg(hw, CARMINE_DCTL_REG + | ||
486 | CARMINE_DCTL_REG_RSV0_STATES); | ||
487 | ret &= CARMINE_DCTL_REG_STATES_MASK; | ||
488 | if (!ret) | ||
489 | break; | ||
490 | |||
491 | mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL); | ||
492 | } | ||
493 | |||
494 | if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) { | ||
495 | printk(KERN_ERR "DRAM init failed\n"); | ||
496 | return -EIO; | ||
497 | } | ||
498 | } | ||
499 | |||
500 | flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 | | ||
501 | CARMINE_DFLT_IP_DCTL_ADD; | ||
502 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags); | ||
503 | |||
504 | flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 | | ||
505 | CARMINE_DFLT_IP_DCTL_STATES_AFT_RST; | ||
506 | c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES, | ||
507 | flags); | ||
508 | |||
509 | /* Initialize the write back register */ | ||
510 | c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM, | ||
511 | CARMINE_WB_REG_WBM_DEFAULT); | ||
512 | |||
513 | /* Initialize the Kottos registers */ | ||
514 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0); | ||
515 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0); | ||
516 | |||
517 | /* Set DC offsets */ | ||
518 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0); | ||
519 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0); | ||
520 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0); | ||
521 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0); | ||
522 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0); | ||
523 | c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0); | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static struct fb_ops carminefb_ops = { | ||
528 | .owner = THIS_MODULE, | ||
529 | .fb_fillrect = cfb_fillrect, | ||
530 | .fb_copyarea = cfb_copyarea, | ||
531 | .fb_imageblit = cfb_imageblit, | ||
532 | |||
533 | .fb_check_var = carmine_check_var, | ||
534 | .fb_set_par = carmine_set_par, | ||
535 | .fb_setcolreg = carmine_setcolreg, | ||
536 | }; | ||
537 | |||
538 | static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base, | ||
539 | int smem_offset, struct device *device, struct fb_info **rinfo) | ||
540 | { | ||
541 | int ret; | ||
542 | struct fb_info *info; | ||
543 | struct carmine_fb *par; | ||
544 | |||
545 | info = framebuffer_alloc(sizeof *par, device); | ||
546 | if (!info) | ||
547 | return -ENOMEM; | ||
548 | |||
549 | par = info->par; | ||
550 | par->display_reg = regs; | ||
551 | par->smem_offset = smem_offset; | ||
552 | |||
553 | info->screen_base = smem_base + smem_offset; | ||
554 | info->screen_size = CARMINE_DISPLAY_MEM; | ||
555 | info->fbops = &carminefb_ops; | ||
556 | |||
557 | info->fix = carminefb_fix; | ||
558 | info->pseudo_palette = par->pseudo_palette; | ||
559 | info->flags = FBINFO_DEFAULT; | ||
560 | |||
561 | ret = fb_alloc_cmap(&info->cmap, 256, 1); | ||
562 | if (ret < 0) | ||
563 | goto err_free_fb; | ||
564 | |||
565 | if (fb_mode > ARRAY_SIZE(carmine_modedb)) | ||
566 | fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; | ||
567 | |||
568 | par->cur_mode = par->new_mode = ~0; | ||
569 | |||
570 | ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb, | ||
571 | ARRAY_SIZE(carmine_modedb), | ||
572 | &carmine_modedb[fb_mode], 32); | ||
573 | if (!ret || ret == 4) { | ||
574 | ret = -EINVAL; | ||
575 | goto err_dealloc_cmap; | ||
576 | } | ||
577 | |||
578 | fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb), | ||
579 | &info->modelist); | ||
580 | |||
581 | ret = register_framebuffer(info); | ||
582 | if (ret < 0) | ||
583 | goto err_dealloc_cmap; | ||
584 | |||
585 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | ||
586 | info->fix.id); | ||
587 | |||
588 | *rinfo = info; | ||
589 | return 0; | ||
590 | |||
591 | err_dealloc_cmap: | ||
592 | fb_dealloc_cmap(&info->cmap); | ||
593 | err_free_fb: | ||
594 | framebuffer_release(info); | ||
595 | return ret; | ||
596 | } | ||
597 | |||
598 | static void cleanup_fb_device(struct fb_info *info) | ||
599 | { | ||
600 | if (info) { | ||
601 | unregister_framebuffer(info); | ||
602 | fb_dealloc_cmap(&info->cmap); | ||
603 | framebuffer_release(info); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static int __devinit carminefb_probe(struct pci_dev *dev, | ||
608 | const struct pci_device_id *ent) | ||
609 | { | ||
610 | struct carmine_hw *hw; | ||
611 | struct device *device = &dev->dev; | ||
612 | struct fb_info *info; | ||
613 | int ret; | ||
614 | |||
615 | ret = pci_enable_device(dev); | ||
616 | if (ret) | ||
617 | return ret; | ||
618 | |||
619 | ret = -ENOMEM; | ||
620 | hw = kzalloc(sizeof *hw, GFP_KERNEL); | ||
621 | if (!hw) | ||
622 | goto err_enable_pci; | ||
623 | |||
624 | carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR); | ||
625 | carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR); | ||
626 | |||
627 | if (!request_mem_region(carminefb_fix.mmio_start, | ||
628 | carminefb_fix.mmio_len, | ||
629 | "carminefb regbase")) { | ||
630 | printk(KERN_ERR "carminefb: Can't reserve regbase.\n"); | ||
631 | ret = -EBUSY; | ||
632 | goto err_free_hw; | ||
633 | } | ||
634 | hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start, | ||
635 | carminefb_fix.mmio_len); | ||
636 | if (!hw->v_regs) { | ||
637 | printk(KERN_ERR "carminefb: Can't remap %s register.\n", | ||
638 | carminefb_fix.id); | ||
639 | goto err_free_reg_mmio; | ||
640 | } | ||
641 | |||
642 | carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR); | ||
643 | carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR); | ||
644 | |||
645 | /* The memory area tends to be very large (256 MiB). Remap only what | ||
646 | * is required for that largest resolution to avoid remaps at run | ||
647 | * time | ||
648 | */ | ||
649 | if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM) | ||
650 | carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM; | ||
651 | |||
652 | else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) { | ||
653 | printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d " | ||
654 | "are required.", carminefb_fix.smem_len, | ||
655 | CARMINE_TOTAL_DIPLAY_MEM); | ||
656 | goto err_free_reg_mmio; | ||
657 | } | ||
658 | |||
659 | if (!request_mem_region(carminefb_fix.smem_start, | ||
660 | carminefb_fix.smem_len, "carminefb smem")) { | ||
661 | printk(KERN_ERR "carminefb: Can't reserve smem.\n"); | ||
662 | goto err_unmap_vregs; | ||
663 | } | ||
664 | |||
665 | hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start, | ||
666 | carminefb_fix.smem_len); | ||
667 | if (!hw->screen_mem) { | ||
668 | printk(KERN_ERR "carmine: Can't ioremap smem area.\n"); | ||
669 | release_mem_region(carminefb_fix.smem_start, | ||
670 | carminefb_fix.smem_len); | ||
671 | goto err_reg_smem; | ||
672 | } | ||
673 | |||
674 | ret = init_hardware(hw); | ||
675 | if (ret) | ||
676 | goto err_unmap_screen; | ||
677 | |||
678 | info = NULL; | ||
679 | if (fb_displays & CARMINE_USE_DISPLAY0) { | ||
680 | ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG, | ||
681 | hw->screen_mem, CARMINE_DISPLAY_MEM * 0, | ||
682 | device, &info); | ||
683 | if (ret) | ||
684 | goto err_deinit_hw; | ||
685 | } | ||
686 | |||
687 | hw->fb[0] = info; | ||
688 | |||
689 | info = NULL; | ||
690 | if (fb_displays & CARMINE_USE_DISPLAY1) { | ||
691 | ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG, | ||
692 | hw->screen_mem, CARMINE_DISPLAY_MEM * 1, | ||
693 | device, &info); | ||
694 | if (ret) | ||
695 | goto err_cleanup_fb0; | ||
696 | } | ||
697 | |||
698 | hw->fb[1] = info; | ||
699 | info = NULL; | ||
700 | |||
701 | pci_set_drvdata(dev, hw); | ||
702 | return 0; | ||
703 | |||
704 | err_cleanup_fb0: | ||
705 | cleanup_fb_device(hw->fb[0]); | ||
706 | err_deinit_hw: | ||
707 | /* disable clock, etc */ | ||
708 | c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0); | ||
709 | err_unmap_screen: | ||
710 | iounmap(hw->screen_mem); | ||
711 | err_reg_smem: | ||
712 | release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len); | ||
713 | err_unmap_vregs: | ||
714 | iounmap(hw->v_regs); | ||
715 | err_free_reg_mmio: | ||
716 | release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len); | ||
717 | err_free_hw: | ||
718 | kfree(hw); | ||
719 | err_enable_pci: | ||
720 | pci_disable_device(dev); | ||
721 | return ret; | ||
722 | } | ||
723 | |||
724 | static void __devexit carminefb_remove(struct pci_dev *dev) | ||
725 | { | ||
726 | struct carmine_hw *hw = pci_get_drvdata(dev); | ||
727 | struct fb_fix_screeninfo fix; | ||
728 | int i; | ||
729 | |||
730 | /* in case we use only fb1 and not fb1 */ | ||
731 | if (hw->fb[0]) | ||
732 | fix = hw->fb[0]->fix; | ||
733 | else | ||
734 | fix = hw->fb[1]->fix; | ||
735 | |||
736 | /* deactivate display(s) and switch clocks */ | ||
737 | c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0); | ||
738 | c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0); | ||
739 | c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0); | ||
740 | |||
741 | for (i = 0; i < MAX_DISPLAY; i++) | ||
742 | cleanup_fb_device(hw->fb[i]); | ||
743 | |||
744 | iounmap(hw->screen_mem); | ||
745 | release_mem_region(fix.smem_start, fix.smem_len); | ||
746 | iounmap(hw->v_regs); | ||
747 | release_mem_region(fix.mmio_start, fix.mmio_len); | ||
748 | |||
749 | pci_set_drvdata(dev, NULL); | ||
750 | pci_disable_device(dev); | ||
751 | kfree(hw); | ||
752 | } | ||
753 | |||
754 | #define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf | ||
755 | static struct pci_device_id carmine_devices[] __devinitdata = { | ||
756 | { | ||
757 | PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)}, | ||
758 | {0, 0, 0, 0, 0, 0, 0} | ||
759 | }; | ||
760 | |||
761 | MODULE_DEVICE_TABLE(pci, carmine_devices); | ||
762 | |||
763 | static struct pci_driver carmine_pci_driver = { | ||
764 | .name = "carminefb", | ||
765 | .id_table = carmine_devices, | ||
766 | .probe = carminefb_probe, | ||
767 | .remove = __devexit_p(carminefb_remove), | ||
768 | }; | ||
769 | |||
770 | static int __init carminefb_init(void) | ||
771 | { | ||
772 | if (!(fb_displays & | ||
773 | (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) { | ||
774 | printk(KERN_ERR "If you disable both displays than you don't " | ||
775 | "need the driver at all\n"); | ||
776 | return -EINVAL; | ||
777 | } | ||
778 | return pci_register_driver(&carmine_pci_driver); | ||
779 | } | ||
780 | module_init(carminefb_init); | ||
781 | |||
782 | static void __exit carminefb_cleanup(void) | ||
783 | { | ||
784 | pci_unregister_driver(&carmine_pci_driver); | ||
785 | } | ||
786 | module_exit(carminefb_cleanup); | ||
787 | |||
788 | MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>"); | ||
789 | MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices"); | ||
790 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/carminefb.h b/drivers/video/carminefb.h new file mode 100644 index 000000000000..05306de0c6b6 --- /dev/null +++ b/drivers/video/carminefb.h | |||
@@ -0,0 +1,64 @@ | |||
1 | #ifndef CARMINE_CARMINE_H | ||
2 | #define CARMINE_CARMINE_H | ||
3 | |||
4 | #define CARMINE_MEMORY_BAR 2 | ||
5 | #define CARMINE_CONFIG_BAR 3 | ||
6 | |||
7 | #define MAX_DISPLAY 2 | ||
8 | #define CARMINE_DISPLAY_MEM (800 * 600 * 4) | ||
9 | #define CARMINE_TOTAL_DIPLAY_MEM (CARMINE_DISPLAY_MEM * MAX_DISPLAY) | ||
10 | |||
11 | #define CARMINE_USE_DISPLAY0 (1 << 0) | ||
12 | #define CARMINE_USE_DISPLAY1 (1 << 1) | ||
13 | |||
14 | /* | ||
15 | * This values work on the eval card. Custom boards may use different timings, | ||
16 | * here an example :) | ||
17 | */ | ||
18 | |||
19 | /* DRAM initialization values */ | ||
20 | #ifdef CONFIG_FB_CARMINE_DRAM_EVAL | ||
21 | |||
22 | #define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff) | ||
23 | #define CARMINE_DFLT_IP_DCTL_ADD (0x05c3) | ||
24 | #define CARMINE_DFLT_IP_DCTL_MODE (0x0121) | ||
25 | #define CARMINE_DFLT_IP_DCTL_EMODE (0x8000) | ||
26 | #define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x4749) | ||
27 | #define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x2a22) | ||
28 | #define CARMINE_DFLT_IP_DCTL_REFRESH (0x0042) | ||
29 | #define CARMINE_DFLT_IP_DCTL_STATES (0x0003) | ||
30 | #define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020) | ||
31 | #define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f) | ||
32 | #define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000) | ||
33 | #define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x6646) | ||
34 | #define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x0055) | ||
35 | #define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0021) | ||
36 | #define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002) | ||
37 | #define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555) | ||
38 | #define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555) | ||
39 | #define CARMINE_DCTL_DLL_RESET (1) | ||
40 | #endif | ||
41 | |||
42 | #ifdef CONFIG_CARMINE_DRAM_CUSTOM | ||
43 | |||
44 | #define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff) | ||
45 | #define CARMINE_DFLT_IP_DCTL_ADD (0x03b2) | ||
46 | #define CARMINE_DFLT_IP_DCTL_MODE (0x0161) | ||
47 | #define CARMINE_DFLT_IP_DCTL_EMODE (0x8000) | ||
48 | #define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x2628) | ||
49 | #define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x1a09) | ||
50 | #define CARMINE_DFLT_IP_DCTL_REFRESH (0x00fe) | ||
51 | #define CARMINE_DFLT_IP_DCTL_STATES (0x0003) | ||
52 | #define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020) | ||
53 | #define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f) | ||
54 | #define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000) | ||
55 | #define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x0646) | ||
56 | #define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x55aa) | ||
57 | #define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0061) | ||
58 | #define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002) | ||
59 | #define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555) | ||
60 | #define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555) | ||
61 | #define CARMINE_DCTL_DLL_RESET (1) | ||
62 | #endif | ||
63 | |||
64 | #endif | ||
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/carminefb_regs.h new file mode 100644 index 000000000000..045215600b73 --- /dev/null +++ b/drivers/video/carminefb_regs.h | |||
@@ -0,0 +1,159 @@ | |||
1 | #ifndef _CARMINEFB_REGS_H | ||
2 | #define _CARMINEFB_REGS_H | ||
3 | |||
4 | #define CARMINE_OVERLAY_EXT_MODE (0x00000002) | ||
5 | #define CARMINE_GRAPH_REG (0x00000000) | ||
6 | #define CARMINE_DISP0_REG (0x00100000) | ||
7 | #define CARMINE_DISP1_REG (0x00140000) | ||
8 | #define CARMINE_WB_REG (0x00180000) | ||
9 | #define CARMINE_DCTL_REG (0x00300000) | ||
10 | #define CARMINE_CTL_REG (0x00400000) | ||
11 | #define CARMINE_WINDOW_MODE (0x00000001) | ||
12 | #define CARMINE_EXTEND_MODE (CARMINE_WINDOW_MODE | \ | ||
13 | CARMINE_OVERLAY_EXT_MODE) | ||
14 | #define CARMINE_L0E (1 << 16) | ||
15 | #define CARMINE_L2E (1 << 18) | ||
16 | #define CARMINE_DEN (1 << 31) | ||
17 | |||
18 | #define CARMINE_EXT_CMODE_DIRECT24_RGBA (0xC0000000) | ||
19 | #define CARMINE_DCTL_REG_MODE_ADD (0x00) | ||
20 | #define CARMINE_DCTL_REG_SETTIME1_EMODE (0x04) | ||
21 | #define CARMINE_DCTL_REG_REFRESH_SETTIME2 (0x08) | ||
22 | #define CARMINE_DCTL_REG_RSV0_STATES (0x0C) | ||
23 | #define CARMINE_DCTL_REG_RSV2_RSV1 (0x10) | ||
24 | #define CARMINE_DCTL_REG_DDRIF2_DDRIF1 (0x14) | ||
25 | #define CARMINE_DCTL_REG_IOCONT1_IOCONT0 (0x24) | ||
26 | #define CARMINE_DCTL_REG_STATES_MASK (0x000F) | ||
27 | #define CARMINE_DCTL_INIT_WAIT_INTERVAL (1) | ||
28 | #define CARMINE_DCTL_INIT_WAIT_LIMIT (5000) | ||
29 | #define CARMINE_WB_REG_WBM_DEFAULT (0x0001c020) | ||
30 | #define CARMINE_DISP_REG_L0RM (0x1880) | ||
31 | #define CARMINE_DISP_REG_L0PX (0x1884) | ||
32 | #define CARMINE_DISP_REG_L0PY (0x1888) | ||
33 | #define CARMINE_DISP_REG_L2RM (0x18A0) | ||
34 | #define CARMINE_DISP_REG_L2PX (0x18A4) | ||
35 | #define CARMINE_DISP_REG_L2PY (0x18A8) | ||
36 | #define CARMINE_DISP_REG_L3RM (0x18B0) | ||
37 | #define CARMINE_DISP_REG_L3PX (0x18B4) | ||
38 | #define CARMINE_DISP_REG_L3PY (0x18B8) | ||
39 | #define CARMINE_DISP_REG_L4RM (0x18C0) | ||
40 | #define CARMINE_DISP_REG_L4PX (0x18C4) | ||
41 | #define CARMINE_DISP_REG_L4PY (0x18C8) | ||
42 | #define CARMINE_DISP_REG_L5RM (0x18D0) | ||
43 | #define CARMINE_DISP_REG_L5PX (0x18D4) | ||
44 | #define CARMINE_DISP_REG_L5PY (0x18D8) | ||
45 | #define CARMINE_DISP_REG_L6RM (0x1924) | ||
46 | #define CARMINE_DISP_REG_L6PX (0x1928) | ||
47 | #define CARMINE_DISP_REG_L6PY (0x192C) | ||
48 | #define CARMINE_DISP_REG_L7RM (0x1964) | ||
49 | #define CARMINE_DISP_REG_L7PX (0x1968) | ||
50 | #define CARMINE_DISP_REG_L7PY (0x196C) | ||
51 | #define CARMINE_WB_REG_WBM (0x0004) | ||
52 | #define CARMINE_DISP_HTP_SHIFT (16) | ||
53 | #define CARMINE_DISP_HDB_SHIFT (16) | ||
54 | #define CARMINE_DISP_HSW_SHIFT (16) | ||
55 | #define CARMINE_DISP_VSW_SHIFT (24) | ||
56 | #define CARMINE_DISP_VTR_SHIFT (16) | ||
57 | #define CARMINE_DISP_VDP_SHIFT (16) | ||
58 | #define CARMINE_CURSOR_CUTZ_MASK (0x00000100) | ||
59 | #define CARMINE_CURSOR0_PRIORITY_MASK (0x00010000) | ||
60 | #define CARMINE_CURSOR1_PRIORITY_MASK (0x00020000) | ||
61 | #define CARMINE_DISP_WIDTH_SHIFT (16) | ||
62 | #define CARMINE_DISP_WIN_H_SHIFT (16) | ||
63 | #define CARMINE_DISP_REG_H_TOTAL (0x0004) | ||
64 | #define CARMINE_DISP_REG_H_PERIOD (0x0008) | ||
65 | #define CARMINE_DISP_REG_V_H_W_H_POS (0x000C) | ||
66 | #define CARMINE_DISP_REG_V_TOTAL (0x0010) | ||
67 | #define CARMINE_DISP_REG_V_PERIOD_POS (0x0014) | ||
68 | #define CARMINE_DISP_REG_L0_MODE_W_H (0x0020) | ||
69 | #define CARMINE_DISP_REG_L0_ORG_ADR (0x0024) | ||
70 | #define CARMINE_DISP_REG_L0_DISP_ADR (0x0028) | ||
71 | #define CARMINE_DISP_REG_L0_DISP_POS (0x002C) | ||
72 | #define CARMINE_DISP_REG_L1_WIDTH (0x0030) | ||
73 | #define CARMINE_DISP_REG_L1_ORG_ADR (0x0034) | ||
74 | #define CARMINE_DISP_REG_L2_MODE_W_H (0x0040) | ||
75 | #define CARMINE_DISP_REG_L2_ORG_ADR1 (0x0044) | ||
76 | #define CARMINE_DISP_REG_L2_DISP_ADR1 (0x0048) | ||
77 | #define CARMINE_DISP_REG_L2_DISP_POS (0x0054) | ||
78 | #define CARMINE_DISP_REG_L3_MODE_W_H (0x0058) | ||
79 | #define CARMINE_DISP_REG_L3_ORG_ADR1 (0x005C) | ||
80 | #define CARMINE_DISP_REG_L3_DISP_ADR1 (0x0060) | ||
81 | #define CARMINE_DISP_REG_L3_DISP_POS (0x006C) | ||
82 | #define CARMINE_DISP_REG_L4_MODE_W_H (0x0070) | ||
83 | #define CARMINE_DISP_REG_L4_ORG_ADR1 (0x0074) | ||
84 | #define CARMINE_DISP_REG_L4_DISP_ADR1 (0x0078) | ||
85 | #define CARMINE_DISP_REG_L4_DISP_POS (0x0084) | ||
86 | #define CARMINE_DISP_REG_L5_MODE_W_H (0x0088) | ||
87 | #define CARMINE_DISP_REG_L5_ORG_ADR1 (0x008C) | ||
88 | #define CARMINE_DISP_REG_L5_DISP_ADR1 (0x0090) | ||
89 | #define CARMINE_DISP_REG_L5_DISP_POS (0x009C) | ||
90 | #define CARMINE_DISP_REG_CURSOR_MODE (0x00A0) | ||
91 | #define CARMINE_DISP_REG_CUR1_POS (0x00A8) | ||
92 | #define CARMINE_DISP_REG_CUR2_POS (0x00B0) | ||
93 | #define CARMINE_DISP_REG_C_TRANS (0x00BC) | ||
94 | #define CARMINE_DISP_REG_MLMR_TRANS (0x00C0) | ||
95 | #define CARMINE_DISP_REG_L0_EXT_MODE (0x0110) | ||
96 | #define CARMINE_DISP_REG_L0_WIN_POS (0x0114) | ||
97 | #define CARMINE_DISP_REG_L0_WIN_SIZE (0x0118) | ||
98 | #define CARMINE_DISP_REG_L1_EXT_MODE (0x0120) | ||
99 | #define CARMINE_DISP_REG_L1_WIN_POS (0x0124) | ||
100 | #define CARMINE_DISP_REG_L1_WIN_SIZE (0x0128) | ||
101 | #define CARMINE_DISP_REG_L2_EXT_MODE (0x0130) | ||
102 | #define CARMINE_DISP_REG_L2_WIN_POS (0x0134) | ||
103 | #define CARMINE_DISP_REG_L2_WIN_SIZE (0x0138) | ||
104 | #define CARMINE_DISP_REG_L3_EXT_MODE (0x0140) | ||
105 | #define CARMINE_DISP_REG_L3_WIN_POS (0x0144) | ||
106 | #define CARMINE_DISP_REG_L3_WIN_SIZE (0x0148) | ||
107 | #define CARMINE_DISP_REG_L4_EXT_MODE (0x0150) | ||
108 | #define CARMINE_DISP_REG_L4_WIN_POS (0x0154) | ||
109 | #define CARMINE_DISP_REG_L4_WIN_SIZE (0x0158) | ||
110 | #define CARMINE_DISP_REG_L5_EXT_MODE (0x0160) | ||
111 | #define CARMINE_DISP_REG_L5_WIN_POS (0x0164) | ||
112 | #define CARMINE_DISP_REG_L5_WIN_SIZE (0x0168) | ||
113 | #define CARMINE_DISP_REG_L6_EXT_MODE (0x1918) | ||
114 | #define CARMINE_DISP_REG_L6_WIN_POS (0x191c) | ||
115 | #define CARMINE_DISP_REG_L6_WIN_SIZE (0x1920) | ||
116 | #define CARMINE_DISP_REG_L7_EXT_MODE (0x1958) | ||
117 | #define CARMINE_DISP_REG_L7_WIN_POS (0x195c) | ||
118 | #define CARMINE_DISP_REG_L7_WIN_SIZE (0x1960) | ||
119 | #define CARMINE_DISP_REG_BLEND_MODE_L0 (0x00B4) | ||
120 | #define CARMINE_DISP_REG_BLEND_MODE_L1 (0x0188) | ||
121 | #define CARMINE_DISP_REG_BLEND_MODE_L2 (0x018C) | ||
122 | #define CARMINE_DISP_REG_BLEND_MODE_L3 (0x0190) | ||
123 | #define CARMINE_DISP_REG_BLEND_MODE_L4 (0x0194) | ||
124 | #define CARMINE_DISP_REG_BLEND_MODE_L5 (0x0198) | ||
125 | #define CARMINE_DISP_REG_BLEND_MODE_L6 (0x1990) | ||
126 | #define CARMINE_DISP_REG_BLEND_MODE_L7 (0x1994) | ||
127 | #define CARMINE_DISP_REG_L0_TRANS (0x01A0) | ||
128 | #define CARMINE_DISP_REG_L1_TRANS (0x01A4) | ||
129 | #define CARMINE_DISP_REG_L2_TRANS (0x01A8) | ||
130 | #define CARMINE_DISP_REG_L3_TRANS (0x01AC) | ||
131 | #define CARMINE_DISP_REG_L4_TRANS (0x01B0) | ||
132 | #define CARMINE_DISP_REG_L5_TRANS (0x01B4) | ||
133 | #define CARMINE_DISP_REG_L6_TRANS (0x1998) | ||
134 | #define CARMINE_DISP_REG_L7_TRANS (0x199c) | ||
135 | #define CARMINE_EXTEND_MODE_MASK (0x00000003) | ||
136 | #define CARMINE_DISP_DCM_MASK (0x0000FFFF) | ||
137 | #define CARMINE_DISP_REG_DCM1 (0x0100) | ||
138 | #define CARMINE_DISP_WIDTH_UNIT (64) | ||
139 | #define CARMINE_DISP_REG_L6_MODE_W_H (0x1900) | ||
140 | #define CARMINE_DISP_REG_L6_ORG_ADR1 (0x1904) | ||
141 | #define CARMINE_DISP_REG_L6_DISP_ADR0 (0x1908) | ||
142 | #define CARMINE_DISP_REG_L6_DISP_POS (0x1914) | ||
143 | #define CARMINE_DISP_REG_L7_MODE_W_H (0x1940) | ||
144 | #define CARMINE_DISP_REG_L7_ORG_ADR1 (0x1944) | ||
145 | #define CARMINE_DISP_REG_L7_DISP_ADR0 (0x1948) | ||
146 | #define CARMINE_DISP_REG_L7_DISP_POS (0x1954) | ||
147 | #define CARMINE_CTL_REG_CLOCK_ENABLE (0x000C) | ||
148 | #define CARMINE_CTL_REG_SOFTWARE_RESET (0x0010) | ||
149 | #define CARMINE_CTL_REG_IST_MASK_ALL (0x07FFFFFF) | ||
150 | #define CARMINE_GRAPH_REG_VRINTM (0x00028064) | ||
151 | #define CARMINE_GRAPH_REG_VRERRM (0x0002806C) | ||
152 | #define CARMINE_GRAPH_REG_DC_OFFSET_PX (0x0004005C) | ||
153 | #define CARMINE_GRAPH_REG_DC_OFFSET_PY (0x00040060) | ||
154 | #define CARMINE_GRAPH_REG_DC_OFFSET_LX (0x00040064) | ||
155 | #define CARMINE_GRAPH_REG_DC_OFFSET_LY (0x00040068) | ||
156 | #define CARMINE_GRAPH_REG_DC_OFFSET_TX (0x0004006C) | ||
157 | #define CARMINE_GRAPH_REG_DC_OFFSET_TY (0x00040070) | ||
158 | |||
159 | #endif | ||
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index c14b2435d23e..e729fb279645 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -628,27 +628,18 @@ static long cirrusfb_get_mclk(long freq, int bpp, long *div) | |||
628 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | 628 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, |
629 | struct fb_info *info) | 629 | struct fb_info *info) |
630 | { | 630 | { |
631 | int nom, den; /* translyting from pixels->bytes */ | 631 | int yres; |
632 | int yres, i; | 632 | /* memory size in pixels */ |
633 | static struct { int xres, yres; } modes[] = | 633 | unsigned pixels = info->screen_size * 8 / var->bits_per_pixel; |
634 | { { 1600, 1280 }, | ||
635 | { 1280, 1024 }, | ||
636 | { 1024, 768 }, | ||
637 | { 800, 600 }, | ||
638 | { 640, 480 }, | ||
639 | { -1, -1 } }; | ||
640 | 634 | ||
641 | switch (var->bits_per_pixel) { | 635 | switch (var->bits_per_pixel) { |
642 | case 1: | 636 | case 1: |
643 | nom = 4; | 637 | pixels /= 4; |
644 | den = 8; | ||
645 | break; /* 8 pixel per byte, only 1/4th of mem usable */ | 638 | break; /* 8 pixel per byte, only 1/4th of mem usable */ |
646 | case 8: | 639 | case 8: |
647 | case 16: | 640 | case 16: |
648 | case 24: | 641 | case 24: |
649 | case 32: | 642 | case 32: |
650 | nom = var->bits_per_pixel / 8; | ||
651 | den = 1; | ||
652 | break; /* 1 pixel == 1 byte */ | 643 | break; /* 1 pixel == 1 byte */ |
653 | default: | 644 | default: |
654 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." | 645 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." |
@@ -658,43 +649,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
658 | return -EINVAL; | 649 | return -EINVAL; |
659 | } | 650 | } |
660 | 651 | ||
661 | if (var->xres * nom / den * var->yres > info->screen_size) { | 652 | if (var->xres_virtual < var->xres) |
662 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." | 653 | var->xres_virtual = var->xres; |
663 | "resolution too high to fit into video memory!\n", | ||
664 | var->xres, var->yres, var->bits_per_pixel); | ||
665 | DPRINTK("EXIT - EINVAL error\n"); | ||
666 | return -EINVAL; | ||
667 | } | ||
668 | |||
669 | /* use highest possible virtual resolution */ | 654 | /* use highest possible virtual resolution */ |
670 | if (var->xres_virtual == -1 && | 655 | if (var->yres_virtual == -1) { |
671 | var->yres_virtual == -1) { | 656 | var->yres_virtual = pixels / var->xres_virtual; |
672 | printk(KERN_INFO | ||
673 | "cirrusfb: using maximum available virtual resolution\n"); | ||
674 | for (i = 0; modes[i].xres != -1; i++) { | ||
675 | int size = modes[i].xres * nom / den * modes[i].yres; | ||
676 | if (size < info->screen_size / 2) | ||
677 | break; | ||
678 | } | ||
679 | if (modes[i].xres == -1) { | ||
680 | printk(KERN_ERR "cirrusfb: could not find a virtual " | ||
681 | "resolution that fits into video memory!!\n"); | ||
682 | DPRINTK("EXIT - EINVAL error\n"); | ||
683 | return -EINVAL; | ||
684 | } | ||
685 | var->xres_virtual = modes[i].xres; | ||
686 | var->yres_virtual = modes[i].yres; | ||
687 | 657 | ||
688 | printk(KERN_INFO "cirrusfb: virtual resolution set to " | 658 | printk(KERN_INFO "cirrusfb: virtual resolution set to " |
689 | "maximum of %dx%d\n", var->xres_virtual, | 659 | "maximum of %dx%d\n", var->xres_virtual, |
690 | var->yres_virtual); | 660 | var->yres_virtual); |
691 | } | 661 | } |
692 | |||
693 | if (var->xres_virtual < var->xres) | ||
694 | var->xres_virtual = var->xres; | ||
695 | if (var->yres_virtual < var->yres) | 662 | if (var->yres_virtual < var->yres) |
696 | var->yres_virtual = var->yres; | 663 | var->yres_virtual = var->yres; |
697 | 664 | ||
665 | if (var->xres_virtual * var->yres_virtual > pixels) { | ||
666 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... " | ||
667 | "virtual resolution too high to fit into video memory!\n", | ||
668 | var->xres_virtual, var->yres_virtual, | ||
669 | var->bits_per_pixel); | ||
670 | DPRINTK("EXIT - EINVAL error\n"); | ||
671 | return -EINVAL; | ||
672 | } | ||
673 | |||
674 | |||
698 | if (var->xoffset < 0) | 675 | if (var->xoffset < 0) |
699 | var->xoffset = 0; | 676 | var->xoffset = 0; |
700 | if (var->yoffset < 0) | 677 | if (var->yoffset < 0) |
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c index 9f8a389dc7ae..16f5db471ab5 100644 --- a/drivers/video/clps711xfb.c +++ b/drivers/video/clps711xfb.c | |||
@@ -27,12 +27,12 @@ | |||
27 | #include <linux/proc_fs.h> | 27 | #include <linux/proc_fs.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | 29 | ||
30 | #include <asm/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <asm/mach-types.h> | 31 | #include <asm/mach-types.h> |
32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
33 | 33 | ||
34 | #include <asm/hardware/clps7111.h> | 34 | #include <asm/hardware/clps7111.h> |
35 | #include <asm/arch/syspld.h> | 35 | #include <mach/syspld.h> |
36 | 36 | ||
37 | struct fb_info *cfb; | 37 | struct fb_info *cfb; |
38 | 38 | ||
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c new file mode 100644 index 000000000000..7bad24ed04ef --- /dev/null +++ b/drivers/video/cobalt_lcdfb.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * Cobalt server LCD frame buffer driver. | ||
3 | * | ||
4 | * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
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 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/fb.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/uaccess.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | /* | ||
29 | * Cursor position address | ||
30 | * \X 0 1 2 ... 14 15 | ||
31 | * Y+----+----+----+---+----+----+ | ||
32 | * 0|0x00|0x01|0x02|...|0x0e|0x0f| | ||
33 | * +----+----+----+---+----+----+ | ||
34 | * 1|0x40|0x41|0x42|...|0x4e|0x4f| | ||
35 | * +----+----+----+---+----+----+ | ||
36 | */ | ||
37 | #define LCD_DATA_REG_OFFSET 0x10 | ||
38 | #define LCD_XRES_MAX 16 | ||
39 | #define LCD_YRES_MAX 2 | ||
40 | #define LCD_CHARS_MAX 32 | ||
41 | |||
42 | #define LCD_CLEAR 0x01 | ||
43 | #define LCD_CURSOR_MOVE_HOME 0x02 | ||
44 | #define LCD_RESET 0x06 | ||
45 | #define LCD_OFF 0x08 | ||
46 | #define LCD_CURSOR_OFF 0x0c | ||
47 | #define LCD_CURSOR_BLINK_OFF 0x0e | ||
48 | #define LCD_CURSOR_ON 0x0f | ||
49 | #define LCD_ON LCD_CURSOR_ON | ||
50 | #define LCD_CURSOR_MOVE_LEFT 0x10 | ||
51 | #define LCD_CURSOR_MOVE_RIGHT 0x14 | ||
52 | #define LCD_DISPLAY_LEFT 0x18 | ||
53 | #define LCD_DISPLAY_RIGHT 0x1c | ||
54 | #define LCD_PRERESET 0x3f /* execute 4 times continuously */ | ||
55 | #define LCD_BUSY 0x80 | ||
56 | |||
57 | #define LCD_GRAPHIC_MODE 0x40 | ||
58 | #define LCD_TEXT_MODE 0x80 | ||
59 | #define LCD_CUR_POS_MASK 0x7f | ||
60 | |||
61 | #define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK) | ||
62 | #define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE) | ||
63 | |||
64 | static inline void lcd_write_control(struct fb_info *info, u8 control) | ||
65 | { | ||
66 | writel((u32)control << 24, info->screen_base); | ||
67 | } | ||
68 | |||
69 | static inline u8 lcd_read_control(struct fb_info *info) | ||
70 | { | ||
71 | return readl(info->screen_base) >> 24; | ||
72 | } | ||
73 | |||
74 | static inline void lcd_write_data(struct fb_info *info, u8 data) | ||
75 | { | ||
76 | writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET); | ||
77 | } | ||
78 | |||
79 | static inline u8 lcd_read_data(struct fb_info *info) | ||
80 | { | ||
81 | return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24; | ||
82 | } | ||
83 | |||
84 | static int lcd_busy_wait(struct fb_info *info) | ||
85 | { | ||
86 | u8 val = 0; | ||
87 | int timeout = 10, retval = 0; | ||
88 | |||
89 | do { | ||
90 | val = lcd_read_control(info); | ||
91 | val &= LCD_BUSY; | ||
92 | if (val != LCD_BUSY) | ||
93 | break; | ||
94 | |||
95 | if (msleep_interruptible(1)) | ||
96 | return -EINTR; | ||
97 | |||
98 | timeout--; | ||
99 | } while (timeout); | ||
100 | |||
101 | if (val == LCD_BUSY) | ||
102 | retval = -EBUSY; | ||
103 | |||
104 | return retval; | ||
105 | } | ||
106 | |||
107 | static void lcd_clear(struct fb_info *info) | ||
108 | { | ||
109 | int i; | ||
110 | |||
111 | for (i = 0; i < 4; i++) { | ||
112 | udelay(150); | ||
113 | |||
114 | lcd_write_control(info, LCD_PRERESET); | ||
115 | } | ||
116 | |||
117 | udelay(150); | ||
118 | |||
119 | lcd_write_control(info, LCD_CLEAR); | ||
120 | |||
121 | udelay(150); | ||
122 | |||
123 | lcd_write_control(info, LCD_RESET); | ||
124 | } | ||
125 | |||
126 | static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = { | ||
127 | .id = "cobalt-lcd", | ||
128 | .type = FB_TYPE_TEXT, | ||
129 | .type_aux = FB_AUX_TEXT_MDA, | ||
130 | .visual = FB_VISUAL_MONO01, | ||
131 | .line_length = LCD_XRES_MAX, | ||
132 | .accel = FB_ACCEL_NONE, | ||
133 | }; | ||
134 | |||
135 | static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf, | ||
136 | size_t count, loff_t *ppos) | ||
137 | { | ||
138 | char src[LCD_CHARS_MAX]; | ||
139 | unsigned long pos; | ||
140 | int len, retval = 0; | ||
141 | |||
142 | pos = *ppos; | ||
143 | if (pos >= LCD_CHARS_MAX || count == 0) | ||
144 | return 0; | ||
145 | |||
146 | if (count > LCD_CHARS_MAX) | ||
147 | count = LCD_CHARS_MAX; | ||
148 | |||
149 | if (pos + count > LCD_CHARS_MAX) | ||
150 | count = LCD_CHARS_MAX - pos; | ||
151 | |||
152 | for (len = 0; len < count; len++) { | ||
153 | retval = lcd_busy_wait(info); | ||
154 | if (retval < 0) | ||
155 | break; | ||
156 | |||
157 | lcd_write_control(info, LCD_TEXT_POS(pos)); | ||
158 | |||
159 | retval = lcd_busy_wait(info); | ||
160 | if (retval < 0) | ||
161 | break; | ||
162 | |||
163 | src[len] = lcd_read_data(info); | ||
164 | if (pos == 0x0f) | ||
165 | pos = 0x40; | ||
166 | else | ||
167 | pos++; | ||
168 | } | ||
169 | |||
170 | if (retval < 0 && signal_pending(current)) | ||
171 | return -ERESTARTSYS; | ||
172 | |||
173 | if (copy_to_user(buf, src, len)) | ||
174 | return -EFAULT; | ||
175 | |||
176 | *ppos += len; | ||
177 | |||
178 | return len; | ||
179 | } | ||
180 | |||
181 | static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf, | ||
182 | size_t count, loff_t *ppos) | ||
183 | { | ||
184 | char dst[LCD_CHARS_MAX]; | ||
185 | unsigned long pos; | ||
186 | int len, retval = 0; | ||
187 | |||
188 | pos = *ppos; | ||
189 | if (pos >= LCD_CHARS_MAX || count == 0) | ||
190 | return 0; | ||
191 | |||
192 | if (count > LCD_CHARS_MAX) | ||
193 | count = LCD_CHARS_MAX; | ||
194 | |||
195 | if (pos + count > LCD_CHARS_MAX) | ||
196 | count = LCD_CHARS_MAX - pos; | ||
197 | |||
198 | if (copy_from_user(dst, buf, count)) | ||
199 | return -EFAULT; | ||
200 | |||
201 | for (len = 0; len < count; len++) { | ||
202 | retval = lcd_busy_wait(info); | ||
203 | if (retval < 0) | ||
204 | break; | ||
205 | |||
206 | lcd_write_control(info, LCD_TEXT_POS(pos)); | ||
207 | |||
208 | retval = lcd_busy_wait(info); | ||
209 | if (retval < 0) | ||
210 | break; | ||
211 | |||
212 | lcd_write_data(info, dst[len]); | ||
213 | if (pos == 0x0f) | ||
214 | pos = 0x40; | ||
215 | else | ||
216 | pos++; | ||
217 | } | ||
218 | |||
219 | if (retval < 0 && signal_pending(current)) | ||
220 | return -ERESTARTSYS; | ||
221 | |||
222 | *ppos += len; | ||
223 | |||
224 | return len; | ||
225 | } | ||
226 | |||
227 | static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info) | ||
228 | { | ||
229 | int retval; | ||
230 | |||
231 | retval = lcd_busy_wait(info); | ||
232 | if (retval < 0) | ||
233 | return retval; | ||
234 | |||
235 | switch (blank_mode) { | ||
236 | case FB_BLANK_UNBLANK: | ||
237 | lcd_write_control(info, LCD_ON); | ||
238 | break; | ||
239 | default: | ||
240 | lcd_write_control(info, LCD_OFF); | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
248 | { | ||
249 | u32 x, y; | ||
250 | int retval; | ||
251 | |||
252 | switch (cursor->set) { | ||
253 | case FB_CUR_SETPOS: | ||
254 | x = cursor->image.dx; | ||
255 | y = cursor->image.dy; | ||
256 | if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX) | ||
257 | return -EINVAL; | ||
258 | |||
259 | retval = lcd_busy_wait(info); | ||
260 | if (retval < 0) | ||
261 | return retval; | ||
262 | |||
263 | lcd_write_control(info, | ||
264 | LCD_TEXT_POS(info->fix.line_length * y + x)); | ||
265 | break; | ||
266 | default: | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | retval = lcd_busy_wait(info); | ||
271 | if (retval < 0) | ||
272 | return retval; | ||
273 | |||
274 | if (cursor->enable) | ||
275 | lcd_write_control(info, LCD_CURSOR_ON); | ||
276 | else | ||
277 | lcd_write_control(info, LCD_CURSOR_OFF); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static struct fb_ops cobalt_lcd_fbops = { | ||
283 | .owner = THIS_MODULE, | ||
284 | .fb_read = cobalt_lcdfb_read, | ||
285 | .fb_write = cobalt_lcdfb_write, | ||
286 | .fb_blank = cobalt_lcdfb_blank, | ||
287 | .fb_cursor = cobalt_lcdfb_cursor, | ||
288 | }; | ||
289 | |||
290 | static int __init cobalt_lcdfb_probe(struct platform_device *dev) | ||
291 | { | ||
292 | struct fb_info *info; | ||
293 | struct resource *res; | ||
294 | int retval; | ||
295 | |||
296 | info = framebuffer_alloc(0, &dev->dev); | ||
297 | if (!info) | ||
298 | return -ENOMEM; | ||
299 | |||
300 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
301 | if (!res) { | ||
302 | framebuffer_release(info); | ||
303 | return -EBUSY; | ||
304 | } | ||
305 | |||
306 | info->screen_size = res->end - res->start + 1; | ||
307 | info->screen_base = ioremap(res->start, info->screen_size); | ||
308 | info->fbops = &cobalt_lcd_fbops; | ||
309 | info->fix = cobalt_lcdfb_fix; | ||
310 | info->fix.smem_start = res->start; | ||
311 | info->fix.smem_len = info->screen_size; | ||
312 | info->pseudo_palette = NULL; | ||
313 | info->par = NULL; | ||
314 | info->flags = FBINFO_DEFAULT; | ||
315 | |||
316 | retval = register_framebuffer(info); | ||
317 | if (retval < 0) { | ||
318 | iounmap(info->screen_base); | ||
319 | framebuffer_release(info); | ||
320 | return retval; | ||
321 | } | ||
322 | |||
323 | platform_set_drvdata(dev, info); | ||
324 | |||
325 | lcd_clear(info); | ||
326 | |||
327 | printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n", | ||
328 | info->node); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int __devexit cobalt_lcdfb_remove(struct platform_device *dev) | ||
334 | { | ||
335 | struct fb_info *info; | ||
336 | |||
337 | info = platform_get_drvdata(dev); | ||
338 | if (info) { | ||
339 | iounmap(info->screen_base); | ||
340 | unregister_framebuffer(info); | ||
341 | framebuffer_release(info); | ||
342 | } | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static struct platform_driver cobalt_lcdfb_driver = { | ||
348 | .probe = cobalt_lcdfb_probe, | ||
349 | .remove = __devexit_p(cobalt_lcdfb_remove), | ||
350 | .driver = { | ||
351 | .name = "cobalt-lcd", | ||
352 | .owner = THIS_MODULE, | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | static int __init cobalt_lcdfb_init(void) | ||
357 | { | ||
358 | return platform_driver_register(&cobalt_lcdfb_driver); | ||
359 | } | ||
360 | |||
361 | static void __exit cobalt_lcdfb_exit(void) | ||
362 | { | ||
363 | platform_driver_unregister(&cobalt_lcdfb_driver); | ||
364 | } | ||
365 | |||
366 | module_init(cobalt_lcdfb_init); | ||
367 | module_exit(cobalt_lcdfb_exit); | ||
368 | |||
369 | MODULE_LICENSE("GPL v2"); | ||
370 | MODULE_AUTHOR("Yoichi Yuasa"); | ||
371 | MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver"); | ||
diff --git a/drivers/video/console/.gitignore b/drivers/video/console/.gitignore new file mode 100644 index 000000000000..0c258b45439c --- /dev/null +++ b/drivers/video/console/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | # conmakehash generated file | ||
2 | promcon_tbl.c | ||
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 97aff8db10bf..c6299e8a041d 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -107,9 +107,7 @@ static struct display fb_display[MAX_NR_CONSOLES]; | |||
107 | 107 | ||
108 | static signed char con2fb_map[MAX_NR_CONSOLES]; | 108 | static signed char con2fb_map[MAX_NR_CONSOLES]; |
109 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; | 109 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
110 | #ifndef MODULE | 110 | |
111 | static int logo_height; | ||
112 | #endif | ||
113 | static int logo_lines; | 111 | static int logo_lines; |
114 | /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO | 112 | /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO |
115 | enums. */ | 113 | enums. */ |
@@ -607,6 +605,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, | |||
607 | struct fbcon_ops *ops = info->fbcon_par; | 605 | struct fbcon_ops *ops = info->fbcon_par; |
608 | int cnt, erase = vc->vc_video_erase_char, step; | 606 | int cnt, erase = vc->vc_video_erase_char, step; |
609 | unsigned short *save = NULL, *r, *q; | 607 | unsigned short *save = NULL, *r, *q; |
608 | int logo_height; | ||
610 | 609 | ||
611 | if (info->flags & FBINFO_MODULE) { | 610 | if (info->flags & FBINFO_MODULE) { |
612 | logo_shown = FBCON_LOGO_DONTSHOW; | 611 | logo_shown = FBCON_LOGO_DONTSHOW; |
@@ -1312,6 +1311,9 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, | |||
1312 | if (!height || !width) | 1311 | if (!height || !width) |
1313 | return; | 1312 | return; |
1314 | 1313 | ||
1314 | if (sy < vc->vc_top && vc->vc_top == logo_lines) | ||
1315 | vc->vc_top = 0; | ||
1316 | |||
1315 | /* Split blits that cross physical y_wrap boundary */ | 1317 | /* Split blits that cross physical y_wrap boundary */ |
1316 | 1318 | ||
1317 | y_break = p->vrows - p->yscroll; | 1319 | y_break = p->vrows - p->yscroll; |
@@ -2516,7 +2518,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, | |||
2516 | c = vc->vc_video_erase_char; | 2518 | c = vc->vc_video_erase_char; |
2517 | vc->vc_video_erase_char = | 2519 | vc->vc_video_erase_char = |
2518 | ((c & 0xfe00) >> 1) | (c & 0xff); | 2520 | ((c & 0xfe00) >> 1) | (c & 0xff); |
2519 | c = vc->vc_def_color; | 2521 | c = vc->vc_scrl_erase_char; |
2520 | vc->vc_scrl_erase_char = | 2522 | vc->vc_scrl_erase_char = |
2521 | ((c & 0xFE00) >> 1) | (c & 0xFF); | 2523 | ((c & 0xFE00) >> 1) | (c & 0xFF); |
2522 | vc->vc_attr >>= 1; | 2524 | vc->vc_attr >>= 1; |
@@ -2549,7 +2551,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, | |||
2549 | if (vc->vc_can_do_color) { | 2551 | if (vc->vc_can_do_color) { |
2550 | vc->vc_video_erase_char = | 2552 | vc->vc_video_erase_char = |
2551 | ((c & 0xff00) << 1) | (c & 0xff); | 2553 | ((c & 0xff00) << 1) | (c & 0xff); |
2552 | c = vc->vc_def_color; | 2554 | c = vc->vc_scrl_erase_char; |
2553 | vc->vc_scrl_erase_char = | 2555 | vc->vc_scrl_erase_char = |
2554 | ((c & 0xFF00) << 1) | (c & 0xFF); | 2556 | ((c & 0xFF00) << 1) | (c & 0xFF); |
2555 | vc->vc_attr <<= 1; | 2557 | vc->vc_attr <<= 1; |
@@ -3586,7 +3588,8 @@ static int __init fb_console_init(void) | |||
3586 | 3588 | ||
3587 | acquire_console_sem(); | 3589 | acquire_console_sem(); |
3588 | fb_register_client(&fbcon_event_notifier); | 3590 | fb_register_client(&fbcon_event_notifier); |
3589 | fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon"); | 3591 | fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0), |
3592 | NULL, "fbcon"); | ||
3590 | 3593 | ||
3591 | if (IS_ERR(fbcon_device)) { | 3594 | if (IS_ERR(fbcon_device)) { |
3592 | printk(KERN_WARNING "Unable to create device " | 3595 | printk(KERN_WARNING "Unable to create device " |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 0135e0395456..a6e38e9ea73f 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -146,10 +146,8 @@ static inline int attr_col_ec(int shift, struct vc_data *vc, | |||
146 | return is_fg ? fg : bg; | 146 | return is_fg ? fg : bg; |
147 | } | 147 | } |
148 | 148 | ||
149 | #define attr_bgcol_ec(bgshift,vc,info) \ | 149 | #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) |
150 | attr_col_ec(bgshift,vc,info,0); | 150 | #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) |
151 | #define attr_fgcol_ec(fgshift,vc,info) \ | ||
152 | attr_col_ec(fgshift,vc,info,1); | ||
153 | 151 | ||
154 | /* Font */ | 152 | /* Font */ |
155 | #define REFCOUNT(fd) (((int *)(fd))[-1]) | 153 | #define REFCOUNT(fd) (((int *)(fd))[-1]) |
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 38a296bbdfc9..9901064199bd 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c | |||
@@ -71,13 +71,15 @@ static char *mda_type_name; | |||
71 | 71 | ||
72 | /* console information */ | 72 | /* console information */ |
73 | 73 | ||
74 | static int mda_first_vc = 1; | 74 | static int mda_first_vc = 13; |
75 | static int mda_last_vc = 16; | 75 | static int mda_last_vc = 16; |
76 | 76 | ||
77 | static struct vc_data *mda_display_fg = NULL; | 77 | static struct vc_data *mda_display_fg = NULL; |
78 | 78 | ||
79 | module_param(mda_first_vc, int, 0); | 79 | module_param(mda_first_vc, int, 0); |
80 | MODULE_PARM_DESC(mda_first_vc, "First virtual console. Default: 13"); | ||
80 | module_param(mda_last_vc, int, 0); | 81 | module_param(mda_last_vc, int, 0); |
82 | MODULE_PARM_DESC(mda_last_vc, "Last virtual console. Default: 16"); | ||
81 | 83 | ||
82 | /* MDA register values | 84 | /* MDA register values |
83 | */ | 85 | */ |
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index a11cc2fdd4cd..4055dbdd1b42 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c | |||
@@ -370,7 +370,7 @@ static const struct consw sti_con = { | |||
370 | 370 | ||
371 | 371 | ||
372 | 372 | ||
373 | int __init sticonsole_init(void) | 373 | static int __init sticonsole_init(void) |
374 | { | 374 | { |
375 | /* already initialized ? */ | 375 | /* already initialized ? */ |
376 | if (sticon_sti) | 376 | if (sticon_sti) |
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index e9ab657f0bb7..ef7870f5ea08 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c | |||
@@ -24,12 +24,13 @@ | |||
24 | #include <asm/hardware.h> | 24 | #include <asm/hardware.h> |
25 | #include <asm/parisc-device.h> | 25 | #include <asm/parisc-device.h> |
26 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
27 | #include <asm/grfioctl.h> | ||
27 | 28 | ||
28 | #include "../sticore.h" | 29 | #include "../sticore.h" |
29 | 30 | ||
30 | #define STI_DRIVERVERSION "Version 0.9a" | 31 | #define STI_DRIVERVERSION "Version 0.9a" |
31 | 32 | ||
32 | struct sti_struct *default_sti __read_mostly; | 33 | static struct sti_struct *default_sti __read_mostly; |
33 | 34 | ||
34 | /* number of STI ROMS found and their ptrs to each struct */ | 35 | /* number of STI ROMS found and their ptrs to each struct */ |
35 | static int num_sti_roms __read_mostly; | 36 | static int num_sti_roms __read_mostly; |
@@ -68,8 +69,7 @@ static const struct sti_init_flags default_init_flags = { | |||
68 | .init_cmap_tx = 1, | 69 | .init_cmap_tx = 1, |
69 | }; | 70 | }; |
70 | 71 | ||
71 | int | 72 | static int sti_init_graph(struct sti_struct *sti) |
72 | sti_init_graph(struct sti_struct *sti) | ||
73 | { | 73 | { |
74 | struct sti_init_inptr_ext inptr_ext = { 0, }; | 74 | struct sti_init_inptr_ext inptr_ext = { 0, }; |
75 | struct sti_init_inptr inptr = { | 75 | struct sti_init_inptr inptr = { |
@@ -100,8 +100,7 @@ static const struct sti_conf_flags default_conf_flags = { | |||
100 | .wait = STI_WAIT, | 100 | .wait = STI_WAIT, |
101 | }; | 101 | }; |
102 | 102 | ||
103 | void | 103 | static void sti_inq_conf(struct sti_struct *sti) |
104 | sti_inq_conf(struct sti_struct *sti) | ||
105 | { | 104 | { |
106 | struct sti_conf_inptr inptr = { 0, }; | 105 | struct sti_conf_inptr inptr = { 0, }; |
107 | unsigned long flags; | 106 | unsigned long flags; |
@@ -237,8 +236,8 @@ static void sti_flush(unsigned long start, unsigned long end) | |||
237 | flush_icache_range(start, end); | 236 | flush_icache_range(start, end); |
238 | } | 237 | } |
239 | 238 | ||
240 | void __devinit | 239 | static void __devinit sti_rom_copy(unsigned long base, unsigned long count, |
241 | sti_rom_copy(unsigned long base, unsigned long count, void *dest) | 240 | void *dest) |
242 | { | 241 | { |
243 | unsigned long dest_start = (unsigned long) dest; | 242 | unsigned long dest_start = (unsigned long) dest; |
244 | 243 | ||
@@ -478,8 +477,8 @@ sti_init_glob_cfg(struct sti_struct *sti, | |||
478 | } | 477 | } |
479 | 478 | ||
480 | #ifdef CONFIG_FB | 479 | #ifdef CONFIG_FB |
481 | struct sti_cooked_font * __devinit | 480 | static struct sti_cooked_font __devinit |
482 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) | 481 | *sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) |
483 | { | 482 | { |
484 | const struct font_desc *fbfont; | 483 | const struct font_desc *fbfont; |
485 | unsigned int size, bpc; | 484 | unsigned int size, bpc; |
@@ -534,16 +533,16 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) | |||
534 | return cooked_font; | 533 | return cooked_font; |
535 | } | 534 | } |
536 | #else | 535 | #else |
537 | struct sti_cooked_font * __devinit | 536 | static struct sti_cooked_font __devinit |
538 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) | 537 | *sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) |
539 | { | 538 | { |
540 | return NULL; | 539 | return NULL; |
541 | } | 540 | } |
542 | #endif | 541 | #endif |
543 | 542 | ||
544 | struct sti_cooked_font * __devinit | 543 | static struct sti_cooked_font __devinit |
545 | sti_select_font(struct sti_cooked_rom *rom, | 544 | *sti_select_font(struct sti_cooked_rom *rom, |
546 | int (*search_font_fnc) (struct sti_cooked_rom *,int,int) ) | 545 | int (*search_font_fnc)(struct sti_cooked_rom *, int, int)) |
547 | { | 546 | { |
548 | struct sti_cooked_font *font; | 547 | struct sti_cooked_font *font; |
549 | int i; | 548 | int i; |
@@ -707,8 +706,7 @@ sti_get_bmode_rom (unsigned long address) | |||
707 | return raw; | 706 | return raw; |
708 | } | 707 | } |
709 | 708 | ||
710 | struct sti_rom * __devinit | 709 | static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address) |
711 | sti_get_wmode_rom (unsigned long address) | ||
712 | { | 710 | { |
713 | struct sti_rom *raw; | 711 | struct sti_rom *raw; |
714 | unsigned long size; | 712 | unsigned long size; |
@@ -723,11 +721,12 @@ sti_get_wmode_rom (unsigned long address) | |||
723 | return raw; | 721 | return raw; |
724 | } | 722 | } |
725 | 723 | ||
726 | int __devinit | 724 | static int __devinit sti_read_rom(int wordmode, struct sti_struct *sti, |
727 | sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address) | 725 | unsigned long address) |
728 | { | 726 | { |
729 | struct sti_cooked_rom *cooked; | 727 | struct sti_cooked_rom *cooked; |
730 | struct sti_rom *raw = NULL; | 728 | struct sti_rom *raw = NULL; |
729 | unsigned long revno; | ||
731 | 730 | ||
732 | cooked = kmalloc(sizeof *cooked, GFP_KERNEL); | 731 | cooked = kmalloc(sizeof *cooked, GFP_KERNEL); |
733 | if (!cooked) | 732 | if (!cooked) |
@@ -770,9 +769,35 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address) | |||
770 | sti->graphics_id[1] = raw->graphics_id[1]; | 769 | sti->graphics_id[1] = raw->graphics_id[1]; |
771 | 770 | ||
772 | sti_dump_rom(raw); | 771 | sti_dump_rom(raw); |
773 | 772 | ||
773 | /* check if the ROM routines in this card are compatible */ | ||
774 | if (wordmode || sti->graphics_id[1] != 0x09A02587) | ||
775 | goto ok; | ||
776 | |||
777 | revno = (raw->revno[0] << 8) | raw->revno[1]; | ||
778 | |||
779 | switch (sti->graphics_id[0]) { | ||
780 | case S9000_ID_HCRX: | ||
781 | /* HyperA or HyperB ? */ | ||
782 | if (revno == 0x8408 || revno == 0x840b) | ||
783 | goto msg_not_supported; | ||
784 | break; | ||
785 | case CRT_ID_THUNDER: | ||
786 | if (revno == 0x8509) | ||
787 | goto msg_not_supported; | ||
788 | break; | ||
789 | case CRT_ID_THUNDER2: | ||
790 | if (revno == 0x850c) | ||
791 | goto msg_not_supported; | ||
792 | } | ||
793 | ok: | ||
774 | return 1; | 794 | return 1; |
775 | 795 | ||
796 | msg_not_supported: | ||
797 | printk(KERN_ERR "Sorry, this GSC/STI card is not yet supported.\n"); | ||
798 | printk(KERN_ERR "Please see http://parisc-linux.org/faq/" | ||
799 | "graphics-howto.html for more info.\n"); | ||
800 | /* fall through */ | ||
776 | out_err: | 801 | out_err: |
777 | kfree(raw); | 802 | kfree(raw); |
778 | kfree(cooked); | 803 | kfree(cooked); |
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index d0e4cb618269..41d62632dcdb 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c | |||
@@ -1425,7 +1425,7 @@ static void cyberpro_common_resume(struct cfb_info *cfb) | |||
1425 | 1425 | ||
1426 | #ifdef CONFIG_ARCH_SHARK | 1426 | #ifdef CONFIG_ARCH_SHARK |
1427 | 1427 | ||
1428 | #include <asm/arch/hardware.h> | 1428 | #include <mach/hardware.h> |
1429 | 1429 | ||
1430 | static int __devinit cyberpro_vl_probe(void) | 1430 | static int __devinit cyberpro_vl_probe(void) |
1431 | { | 1431 | { |
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index cc2810ef5de5..2735b79e52a1 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c | |||
@@ -71,7 +71,7 @@ struct epson1355_par { | |||
71 | #if defined(CONFIG_ARM) | 71 | #if defined(CONFIG_ARM) |
72 | 72 | ||
73 | # ifdef CONFIG_ARCH_CEIVA | 73 | # ifdef CONFIG_ARCH_CEIVA |
74 | # include <asm/arch/hardware.h> | 74 | # include <mach/hardware.h> |
75 | # define EPSON1355FB_BASE_PHYS (CEIVA_PHYS_SED1355) | 75 | # define EPSON1355FB_BASE_PHYS (CEIVA_PHYS_SED1355) |
76 | # endif | 76 | # endif |
77 | 77 | ||
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 59df132cc375..4835bdc4e9f1 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = { | |||
114 | .page_mkwrite = fb_deferred_io_mkwrite, | 114 | .page_mkwrite = fb_deferred_io_mkwrite, |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static int fb_deferred_io_set_page_dirty(struct page *page) | ||
118 | { | ||
119 | if (!PageDirty(page)) | ||
120 | SetPageDirty(page); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static const struct address_space_operations fb_deferred_io_aops = { | ||
125 | .set_page_dirty = fb_deferred_io_set_page_dirty, | ||
126 | }; | ||
127 | |||
117 | static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) | 128 | static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) |
118 | { | 129 | { |
119 | vma->vm_ops = &fb_deferred_io_vm_ops; | 130 | vma->vm_ops = &fb_deferred_io_vm_ops; |
@@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info) | |||
163 | } | 174 | } |
164 | EXPORT_SYMBOL_GPL(fb_deferred_io_init); | 175 | EXPORT_SYMBOL_GPL(fb_deferred_io_init); |
165 | 176 | ||
177 | void fb_deferred_io_open(struct fb_info *info, | ||
178 | struct inode *inode, | ||
179 | struct file *file) | ||
180 | { | ||
181 | file->f_mapping->a_ops = &fb_deferred_io_aops; | ||
182 | } | ||
183 | EXPORT_SYMBOL_GPL(fb_deferred_io_open); | ||
184 | |||
166 | void fb_deferred_io_cleanup(struct fb_info *info) | 185 | void fb_deferred_io_cleanup(struct fb_info *info) |
167 | { | 186 | { |
168 | void *screen_base = (void __force *) info->screen_base; | 187 | void *screen_base = (void __force *) info->screen_base; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 33ebdb198daf..98843c2ecf73 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -848,9 +848,8 @@ int | |||
848 | fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) | 848 | fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) |
849 | { | 849 | { |
850 | struct fb_fix_screeninfo *fix = &info->fix; | 850 | struct fb_fix_screeninfo *fix = &info->fix; |
851 | int xoffset = var->xoffset; | 851 | unsigned int yres = info->var.yres; |
852 | int yoffset = var->yoffset; | 852 | int err = 0; |
853 | int err = 0, yres = info->var.yres; | ||
854 | 853 | ||
855 | if (var->yoffset > 0) { | 854 | if (var->yoffset > 0) { |
856 | if (var->vmode & FB_VMODE_YWRAP) { | 855 | if (var->vmode & FB_VMODE_YWRAP) { |
@@ -866,8 +865,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) | |||
866 | (var->xoffset % fix->xpanstep))) | 865 | (var->xoffset % fix->xpanstep))) |
867 | err = -EINVAL; | 866 | err = -EINVAL; |
868 | 867 | ||
869 | if (err || !info->fbops->fb_pan_display || xoffset < 0 || | 868 | if (err || !info->fbops->fb_pan_display || |
870 | yoffset < 0 || var->yoffset + yres > info->var.yres_virtual || | 869 | var->yoffset + yres > info->var.yres_virtual || |
871 | var->xoffset + info->var.xres > info->var.xres_virtual) | 870 | var->xoffset + info->var.xres > info->var.xres_virtual) |
872 | return -EINVAL; | 871 | return -EINVAL; |
873 | 872 | ||
@@ -1345,6 +1344,10 @@ fb_open(struct inode *inode, struct file *file) | |||
1345 | if (res) | 1344 | if (res) |
1346 | module_put(info->fbops->owner); | 1345 | module_put(info->fbops->owner); |
1347 | } | 1346 | } |
1347 | #ifdef CONFIG_FB_DEFERRED_IO | ||
1348 | if (info->fbdefio) | ||
1349 | fb_deferred_io_open(info, inode, file); | ||
1350 | #endif | ||
1348 | out: | 1351 | out: |
1349 | unlock_kernel(); | 1352 | unlock_kernel(); |
1350 | return res; | 1353 | return res; |
@@ -1439,8 +1442,9 @@ register_framebuffer(struct fb_info *fb_info) | |||
1439 | break; | 1442 | break; |
1440 | fb_info->node = i; | 1443 | fb_info->node = i; |
1441 | 1444 | ||
1442 | fb_info->dev = device_create(fb_class, fb_info->device, | 1445 | fb_info->dev = device_create_drvdata(fb_class, fb_info->device, |
1443 | MKDEV(FB_MAJOR, i), "fb%d", i); | 1446 | MKDEV(FB_MAJOR, i), NULL, |
1447 | "fb%d", i); | ||
1444 | if (IS_ERR(fb_info->dev)) { | 1448 | if (IS_ERR(fb_info->dev)) { |
1445 | /* Not fatal */ | 1449 | /* Not fatal */ |
1446 | printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); | 1450 | printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 052e18058498..6a0aa180c266 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -879,7 +879,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) | |||
879 | if (edid_is_timing_block(block)) { | 879 | if (edid_is_timing_block(block)) { |
880 | var->xres = var->xres_virtual = H_ACTIVE; | 880 | var->xres = var->xres_virtual = H_ACTIVE; |
881 | var->yres = var->yres_virtual = V_ACTIVE; | 881 | var->yres = var->yres_virtual = V_ACTIVE; |
882 | var->height = var->width = -1; | 882 | var->height = var->width = 0; |
883 | var->right_margin = H_SYNC_OFFSET; | 883 | var->right_margin = H_SYNC_OFFSET; |
884 | var->left_margin = (H_ACTIVE + H_BLANKING) - | 884 | var->left_margin = (H_ACTIVE + H_BLANKING) - |
885 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); | 885 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 09d7e22c6fef..fb51197d1c98 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -279,58 +279,42 @@ static struct diu_hw dr = { | |||
279 | 279 | ||
280 | static struct diu_pool pool; | 280 | static struct diu_pool pool; |
281 | 281 | ||
282 | /* To allocate memory for framebuffer. First try __get_free_pages(). If it | 282 | /** |
283 | * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate | 283 | * fsl_diu_alloc - allocate memory for the DIU |
284 | * very large memory (more than 4MB). We don't want to allocate all memory | 284 | * @size: number of bytes to allocate |
285 | * in rheap since small memory allocation/deallocation will fragment the | 285 | * @param: returned physical address of memory |
286 | * rheap and make the furture large allocation fail. | 286 | * |
287 | * This function allocates a physically-contiguous block of memory. | ||
287 | */ | 288 | */ |
288 | 289 | static void *fsl_diu_alloc(size_t size, phys_addr_t *phys) | |
289 | static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys) | ||
290 | { | 290 | { |
291 | void *virt; | 291 | void *virt; |
292 | 292 | ||
293 | pr_debug("size=%lu\n", size); | 293 | pr_debug("size=%zu\n", size); |
294 | 294 | ||
295 | virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size)); | 295 | virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); |
296 | if (virt) { | 296 | if (virt) { |
297 | *phys = virt_to_phys(virt); | 297 | *phys = virt_to_phys(virt); |
298 | pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys); | 298 | pr_debug("virt=%p phys=%llx\n", virt, |
299 | return virt; | 299 | (unsigned long long)*phys); |
300 | } | 300 | } |
301 | if (!diu_ops.diu_mem) { | ||
302 | printk(KERN_INFO "%s: no diu_mem." | ||
303 | " To reserve more memory, put 'diufb=15M' " | ||
304 | "in the command line\n", __func__); | ||
305 | return NULL; | ||
306 | } | ||
307 | |||
308 | virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU"); | ||
309 | if (virt) { | ||
310 | *phys = virt_to_bus(virt); | ||
311 | memset(virt, 0, size); | ||
312 | } | ||
313 | |||
314 | pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys); | ||
315 | 301 | ||
316 | return virt; | 302 | return virt; |
317 | } | 303 | } |
318 | 304 | ||
319 | static void fsl_diu_free(void *p, unsigned long size) | 305 | /** |
306 | * fsl_diu_free - release DIU memory | ||
307 | * @virt: pointer returned by fsl_diu_alloc() | ||
308 | * @size: number of bytes allocated by fsl_diu_alloc() | ||
309 | * | ||
310 | * This function releases memory allocated by fsl_diu_alloc(). | ||
311 | */ | ||
312 | static void fsl_diu_free(void *virt, size_t size) | ||
320 | { | 313 | { |
321 | pr_debug("p=%p size=%lu\n", p, size); | 314 | pr_debug("virt=%p size=%zu\n", virt, size); |
322 | |||
323 | if (!p) | ||
324 | return; | ||
325 | 315 | ||
326 | if ((p >= diu_ops.diu_mem) && | 316 | if (virt && size) |
327 | (p < (diu_ops.diu_mem + diu_ops.diu_size))) { | 317 | free_pages_exact(virt, size); |
328 | pr_debug("rh\n"); | ||
329 | rh_free(&diu_ops.diu_rh_info, (unsigned long) p); | ||
330 | } else { | ||
331 | pr_debug("dma\n"); | ||
332 | free_pages((unsigned long)p, get_order(size)); | ||
333 | } | ||
334 | } | 318 | } |
335 | 319 | ||
336 | static int fsl_diu_enable_panel(struct fb_info *info) | 320 | static int fsl_diu_enable_panel(struct fb_info *info) |
@@ -495,6 +479,10 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
495 | base_plane_width = machine_data->fsl_diu_info[0]->var.xres; | 479 | base_plane_width = machine_data->fsl_diu_info[0]->var.xres; |
496 | base_plane_height = machine_data->fsl_diu_info[0]->var.yres; | 480 | base_plane_height = machine_data->fsl_diu_info[0]->var.yres; |
497 | 481 | ||
482 | if (mfbi->x_aoi_d < 0) | ||
483 | mfbi->x_aoi_d = 0; | ||
484 | if (mfbi->y_aoi_d < 0) | ||
485 | mfbi->y_aoi_d = 0; | ||
498 | switch (index) { | 486 | switch (index) { |
499 | case 0: | 487 | case 0: |
500 | if (mfbi->x_aoi_d != 0) | 488 | if (mfbi->x_aoi_d != 0) |
@@ -794,6 +782,22 @@ static void unmap_video_memory(struct fb_info *info) | |||
794 | } | 782 | } |
795 | 783 | ||
796 | /* | 784 | /* |
785 | * Using the fb_var_screeninfo in fb_info we set the aoi of this | ||
786 | * particular framebuffer. It is a light version of fsl_diu_set_par. | ||
787 | */ | ||
788 | static int fsl_diu_set_aoi(struct fb_info *info) | ||
789 | { | ||
790 | struct fb_var_screeninfo *var = &info->var; | ||
791 | struct mfb_info *mfbi = info->par; | ||
792 | struct diu_ad *ad = mfbi->ad; | ||
793 | |||
794 | /* AOI should not be greater than display size */ | ||
795 | ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset); | ||
796 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | /* | ||
797 | * Using the fb_var_screeninfo in fb_info we set the resolution of this | 801 | * Using the fb_var_screeninfo in fb_info we set the resolution of this |
798 | * particular framebuffer. This function alters the fb_fix_screeninfo stored | 802 | * particular framebuffer. This function alters the fb_fix_screeninfo stored |
799 | * in fb_info. It does not alter var in fb_info since we are using that | 803 | * in fb_info. It does not alter var in fb_info since we are using that |
@@ -833,11 +837,11 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
833 | diu_ops.get_pixel_format(var->bits_per_pixel, | 837 | diu_ops.get_pixel_format(var->bits_per_pixel, |
834 | machine_data->monitor_port); | 838 | machine_data->monitor_port); |
835 | ad->addr = cpu_to_le32(info->fix.smem_start); | 839 | ad->addr = cpu_to_le32(info->fix.smem_start); |
836 | ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) | | 840 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | |
837 | var->xres) | mfbi->g_alpha; | 841 | var->xres_virtual) | mfbi->g_alpha; |
838 | /* fix me. AOI should not be greater than display size */ | 842 | /* AOI should not be greater than display size */ |
839 | ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); | 843 | ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); |
840 | ad->offset_xyi = 0; | 844 | ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset); |
841 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); | 845 | ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); |
842 | 846 | ||
843 | /* Disable chroma keying function */ | 847 | /* Disable chroma keying function */ |
@@ -937,6 +941,8 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var, | |||
937 | else | 941 | else |
938 | info->var.vmode &= ~FB_VMODE_YWRAP; | 942 | info->var.vmode &= ~FB_VMODE_YWRAP; |
939 | 943 | ||
944 | fsl_diu_set_aoi(info); | ||
945 | |||
940 | return 0; | 946 | return 0; |
941 | } | 947 | } |
942 | 948 | ||
@@ -1005,7 +1011,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
1005 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", | 1011 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", |
1006 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | 1012 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); |
1007 | fsl_diu_check_var(&info->var, info); | 1013 | fsl_diu_check_var(&info->var, info); |
1008 | fsl_diu_set_par(info); | 1014 | fsl_diu_set_aoi(info); |
1009 | break; | 1015 | break; |
1010 | case MFB_GET_AOID: | 1016 | case MFB_GET_AOID: |
1011 | aoi_d.x_aoi_d = mfbi->x_aoi_d; | 1017 | aoi_d.x_aoi_d = mfbi->x_aoi_d; |
@@ -1665,8 +1671,10 @@ static int __init fsl_diu_init(void) | |||
1665 | } | 1671 | } |
1666 | 1672 | ||
1667 | prop = of_get_property(np, "d-cache-size", NULL); | 1673 | prop = of_get_property(np, "d-cache-size", NULL); |
1668 | if (prop == NULL) | 1674 | if (prop == NULL) { |
1675 | of_node_put(np); | ||
1669 | return -ENODEV; | 1676 | return -ENODEV; |
1677 | } | ||
1670 | 1678 | ||
1671 | /* Freescale PLRU requires 13/8 times the cache size to do a proper | 1679 | /* Freescale PLRU requires 13/8 times the cache size to do a proper |
1672 | displacement flush | 1680 | displacement flush |
@@ -1675,8 +1683,10 @@ static int __init fsl_diu_init(void) | |||
1675 | coherence_data_size /= 8; | 1683 | coherence_data_size /= 8; |
1676 | 1684 | ||
1677 | prop = of_get_property(np, "d-cache-line-size", NULL); | 1685 | prop = of_get_property(np, "d-cache-line-size", NULL); |
1678 | if (prop == NULL) | 1686 | if (prop == NULL) { |
1687 | of_node_put(np); | ||
1679 | return -ENODEV; | 1688 | return -ENODEV; |
1689 | } | ||
1680 | d_cache_line_size = *prop; | 1690 | d_cache_line_size = *prop; |
1681 | 1691 | ||
1682 | of_node_put(np); | 1692 | of_node_put(np); |
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 2e552d5bbb5d..f89c3cce1e0c 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c | |||
@@ -87,6 +87,8 @@ static int gbe_revision; | |||
87 | static int ypan, ywrap; | 87 | static int ypan, ywrap; |
88 | 88 | ||
89 | static uint32_t pseudo_palette[16]; | 89 | static uint32_t pseudo_palette[16]; |
90 | static uint32_t gbe_cmap[256]; | ||
91 | static int gbe_turned_on; /* 0 turned off, 1 turned on */ | ||
90 | 92 | ||
91 | static char *mode_option __initdata = NULL; | 93 | static char *mode_option __initdata = NULL; |
92 | 94 | ||
@@ -208,6 +210,8 @@ void gbe_turn_off(void) | |||
208 | int i; | 210 | int i; |
209 | unsigned int val, x, y, vpixen_off; | 211 | unsigned int val, x, y, vpixen_off; |
210 | 212 | ||
213 | gbe_turned_on = 0; | ||
214 | |||
211 | /* check if pixel counter is on */ | 215 | /* check if pixel counter is on */ |
212 | val = gbe->vt_xy; | 216 | val = gbe->vt_xy; |
213 | if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1) | 217 | if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1) |
@@ -371,6 +375,22 @@ static void gbe_turn_on(void) | |||
371 | } | 375 | } |
372 | if (i == 10000) | 376 | if (i == 10000) |
373 | printk(KERN_ERR "gbefb: turn on DMA timed out\n"); | 377 | printk(KERN_ERR "gbefb: turn on DMA timed out\n"); |
378 | |||
379 | gbe_turned_on = 1; | ||
380 | } | ||
381 | |||
382 | static void gbe_loadcmap(void) | ||
383 | { | ||
384 | int i, j; | ||
385 | |||
386 | for (i = 0; i < 256; i++) { | ||
387 | for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++) | ||
388 | udelay(10); | ||
389 | if (j == 1000) | ||
390 | printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); | ||
391 | |||
392 | gbe->cmap[i] = gbe_cmap[i]; | ||
393 | } | ||
374 | } | 394 | } |
375 | 395 | ||
376 | /* | 396 | /* |
@@ -382,6 +402,7 @@ static int gbefb_blank(int blank, struct fb_info *info) | |||
382 | switch (blank) { | 402 | switch (blank) { |
383 | case FB_BLANK_UNBLANK: /* unblank */ | 403 | case FB_BLANK_UNBLANK: /* unblank */ |
384 | gbe_turn_on(); | 404 | gbe_turn_on(); |
405 | gbe_loadcmap(); | ||
385 | break; | 406 | break; |
386 | 407 | ||
387 | case FB_BLANK_NORMAL: /* blank */ | 408 | case FB_BLANK_NORMAL: /* blank */ |
@@ -796,16 +817,10 @@ static int gbefb_set_par(struct fb_info *info) | |||
796 | gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8); | 817 | gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8); |
797 | 818 | ||
798 | /* Initialize the color map */ | 819 | /* Initialize the color map */ |
799 | for (i = 0; i < 256; i++) { | 820 | for (i = 0; i < 256; i++) |
800 | int j; | 821 | gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24); |
801 | |||
802 | for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++) | ||
803 | udelay(10); | ||
804 | if (j == 1000) | ||
805 | printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); | ||
806 | 822 | ||
807 | gbe->cmap[i] = (i << 8) | (i << 16) | (i << 24); | 823 | gbe_loadcmap(); |
808 | } | ||
809 | 824 | ||
810 | return 0; | 825 | return 0; |
811 | } | 826 | } |
@@ -855,14 +870,17 @@ static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
855 | blue >>= 8; | 870 | blue >>= 8; |
856 | 871 | ||
857 | if (info->var.bits_per_pixel <= 8) { | 872 | if (info->var.bits_per_pixel <= 8) { |
858 | /* wait for the color map FIFO to have a free entry */ | 873 | gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8); |
859 | for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++) | 874 | if (gbe_turned_on) { |
860 | udelay(10); | 875 | /* wait for the color map FIFO to have a free entry */ |
861 | if (i == 1000) { | 876 | for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++) |
862 | printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); | 877 | udelay(10); |
863 | return 1; | 878 | if (i == 1000) { |
879 | printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); | ||
880 | return 1; | ||
881 | } | ||
882 | gbe->cmap[regno] = gbe_cmap[regno]; | ||
864 | } | 883 | } |
865 | gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8); | ||
866 | } else if (regno < 16) { | 884 | } else if (regno < 16) { |
867 | switch (info->var.bits_per_pixel) { | 885 | switch (info->var.bits_per_pixel) { |
868 | case 15: | 886 | case 15: |
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h index 3b9416f4ee20..6a51448fd3f7 100644 --- a/drivers/video/geode/lxfb.h +++ b/drivers/video/geode/lxfb.h | |||
@@ -51,8 +51,6 @@ static inline unsigned int lx_get_pitch(unsigned int xres, int bpp) | |||
51 | } | 51 | } |
52 | 52 | ||
53 | void lx_set_mode(struct fb_info *); | 53 | void lx_set_mode(struct fb_info *); |
54 | void lx_get_gamma(struct fb_info *, unsigned int *, int); | ||
55 | void lx_set_gamma(struct fb_info *, unsigned int *, int); | ||
56 | unsigned int lx_framebuffer_size(void); | 54 | unsigned int lx_framebuffer_size(void); |
57 | int lx_blank_display(struct fb_info *, int); | 55 | int lx_blank_display(struct fb_info *, int); |
58 | void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, | 56 | void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, |
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c index aaef9165ec9b..b1cd49c99356 100644 --- a/drivers/video/geode/lxfb_ops.c +++ b/drivers/video/geode/lxfb_ops.c | |||
@@ -517,25 +517,25 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno, | |||
517 | int lx_blank_display(struct fb_info *info, int blank_mode) | 517 | int lx_blank_display(struct fb_info *info, int blank_mode) |
518 | { | 518 | { |
519 | struct lxfb_par *par = info->par; | 519 | struct lxfb_par *par = info->par; |
520 | u32 dcfg, fp_pm; | 520 | u32 dcfg, misc, fp_pm; |
521 | int blank, hsync, vsync, crt; | 521 | int blank, hsync, vsync; |
522 | 522 | ||
523 | /* CRT power saving modes. */ | 523 | /* CRT power saving modes. */ |
524 | switch (blank_mode) { | 524 | switch (blank_mode) { |
525 | case FB_BLANK_UNBLANK: | 525 | case FB_BLANK_UNBLANK: |
526 | blank = 0; hsync = 1; vsync = 1; crt = 1; | 526 | blank = 0; hsync = 1; vsync = 1; |
527 | break; | 527 | break; |
528 | case FB_BLANK_NORMAL: | 528 | case FB_BLANK_NORMAL: |
529 | blank = 1; hsync = 1; vsync = 1; crt = 1; | 529 | blank = 1; hsync = 1; vsync = 1; |
530 | break; | 530 | break; |
531 | case FB_BLANK_VSYNC_SUSPEND: | 531 | case FB_BLANK_VSYNC_SUSPEND: |
532 | blank = 1; hsync = 1; vsync = 0; crt = 1; | 532 | blank = 1; hsync = 1; vsync = 0; |
533 | break; | 533 | break; |
534 | case FB_BLANK_HSYNC_SUSPEND: | 534 | case FB_BLANK_HSYNC_SUSPEND: |
535 | blank = 1; hsync = 0; vsync = 1; crt = 1; | 535 | blank = 1; hsync = 0; vsync = 1; |
536 | break; | 536 | break; |
537 | case FB_BLANK_POWERDOWN: | 537 | case FB_BLANK_POWERDOWN: |
538 | blank = 1; hsync = 0; vsync = 0; crt = 0; | 538 | blank = 1; hsync = 0; vsync = 0; |
539 | break; | 539 | break; |
540 | default: | 540 | default: |
541 | return -EINVAL; | 541 | return -EINVAL; |
@@ -545,15 +545,23 @@ int lx_blank_display(struct fb_info *info, int blank_mode) | |||
545 | dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN | | 545 | dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN | |
546 | VP_DCFG_CRT_EN); | 546 | VP_DCFG_CRT_EN); |
547 | if (!blank) | 547 | if (!blank) |
548 | dcfg |= VP_DCFG_DAC_BL_EN; | 548 | dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN; |
549 | if (hsync) | 549 | if (hsync) |
550 | dcfg |= VP_DCFG_HSYNC_EN; | 550 | dcfg |= VP_DCFG_HSYNC_EN; |
551 | if (vsync) | 551 | if (vsync) |
552 | dcfg |= VP_DCFG_VSYNC_EN; | 552 | dcfg |= VP_DCFG_VSYNC_EN; |
553 | if (crt) | 553 | |
554 | dcfg |= VP_DCFG_CRT_EN; | ||
555 | write_vp(par, VP_DCFG, dcfg); | 554 | write_vp(par, VP_DCFG, dcfg); |
556 | 555 | ||
556 | misc = read_vp(par, VP_MISC); | ||
557 | |||
558 | if (vsync && hsync) | ||
559 | misc &= ~VP_MISC_DACPWRDN; | ||
560 | else | ||
561 | misc |= VP_MISC_DACPWRDN; | ||
562 | |||
563 | write_vp(par, VP_MISC, misc); | ||
564 | |||
557 | /* Power on/off flat panel */ | 565 | /* Power on/off flat panel */ |
558 | 566 | ||
559 | if (par->output & OUTPUT_PANEL) { | 567 | if (par->output & OUTPUT_PANEL) { |
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index c18880d9db1f..0129c044f6d6 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c | |||
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = { | |||
551 | * Initialization | 551 | * Initialization |
552 | */ | 552 | */ |
553 | 553 | ||
554 | static int __init hgafb_probe(struct device *device) | 554 | static int __init hgafb_probe(struct platform_device *pdev) |
555 | { | 555 | { |
556 | struct fb_info *info; | 556 | struct fb_info *info; |
557 | 557 | ||
@@ -565,7 +565,7 @@ static int __init hgafb_probe(struct device *device) | |||
565 | printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n", | 565 | printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n", |
566 | hga_type_name, hga_vram_len/1024); | 566 | hga_type_name, hga_vram_len/1024); |
567 | 567 | ||
568 | info = framebuffer_alloc(0, NULL); | 568 | info = framebuffer_alloc(0, &pdev->dev); |
569 | if (!info) { | 569 | if (!info) { |
570 | iounmap(hga_vram); | 570 | iounmap(hga_vram); |
571 | return -ENOMEM; | 571 | return -ENOMEM; |
@@ -593,13 +593,13 @@ static int __init hgafb_probe(struct device *device) | |||
593 | 593 | ||
594 | printk(KERN_INFO "fb%d: %s frame buffer device\n", | 594 | printk(KERN_INFO "fb%d: %s frame buffer device\n", |
595 | info->node, info->fix.id); | 595 | info->node, info->fix.id); |
596 | dev_set_drvdata(device, info); | 596 | platform_set_drvdata(pdev, info); |
597 | return 0; | 597 | return 0; |
598 | } | 598 | } |
599 | 599 | ||
600 | static int hgafb_remove(struct device *device) | 600 | static int hgafb_remove(struct platform_device *pdev) |
601 | { | 601 | { |
602 | struct fb_info *info = dev_get_drvdata(device); | 602 | struct fb_info *info = platform_get_drvdata(pdev); |
603 | 603 | ||
604 | hga_txt_mode(); | 604 | hga_txt_mode(); |
605 | hga_clear_screen(); | 605 | hga_clear_screen(); |
@@ -620,16 +620,15 @@ static int hgafb_remove(struct device *device) | |||
620 | return 0; | 620 | return 0; |
621 | } | 621 | } |
622 | 622 | ||
623 | static struct device_driver hgafb_driver = { | 623 | static struct platform_driver hgafb_driver = { |
624 | .name = "hgafb", | ||
625 | .bus = &platform_bus_type, | ||
626 | .probe = hgafb_probe, | 624 | .probe = hgafb_probe, |
627 | .remove = hgafb_remove, | 625 | .remove = hgafb_remove, |
626 | .driver = { | ||
627 | .name = "hgafb", | ||
628 | }, | ||
628 | }; | 629 | }; |
629 | 630 | ||
630 | static struct platform_device hgafb_device = { | 631 | static struct platform_device *hgafb_device; |
631 | .name = "hgafb", | ||
632 | }; | ||
633 | 632 | ||
634 | static int __init hgafb_init(void) | 633 | static int __init hgafb_init(void) |
635 | { | 634 | { |
@@ -638,12 +637,15 @@ static int __init hgafb_init(void) | |||
638 | if (fb_get_options("hgafb", NULL)) | 637 | if (fb_get_options("hgafb", NULL)) |
639 | return -ENODEV; | 638 | return -ENODEV; |
640 | 639 | ||
641 | ret = driver_register(&hgafb_driver); | 640 | ret = platform_driver_register(&hgafb_driver); |
642 | 641 | ||
643 | if (!ret) { | 642 | if (!ret) { |
644 | ret = platform_device_register(&hgafb_device); | 643 | hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0); |
645 | if (ret) | 644 | |
646 | driver_unregister(&hgafb_driver); | 645 | if (IS_ERR(hgafb_device)) { |
646 | platform_driver_unregister(&hgafb_driver); | ||
647 | ret = PTR_ERR(hgafb_device); | ||
648 | } | ||
647 | } | 649 | } |
648 | 650 | ||
649 | return ret; | 651 | return ret; |
@@ -651,8 +653,8 @@ static int __init hgafb_init(void) | |||
651 | 653 | ||
652 | static void __exit hgafb_exit(void) | 654 | static void __exit hgafb_exit(void) |
653 | { | 655 | { |
654 | platform_device_unregister(&hgafb_device); | 656 | platform_device_unregister(hgafb_device); |
655 | driver_unregister(&hgafb_driver); | 657 | platform_driver_unregister(&hgafb_driver); |
656 | } | 658 | } |
657 | 659 | ||
658 | /* ------------------------------------------------------------------------- | 660 | /* ------------------------------------------------------------------------- |
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 392a8be6aa76..e6467cf9f19f 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <asm/pgtable.h> | 27 | #include <asm/pgtable.h> |
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | #include <asm/hd64461.h> | 29 | #include <asm/hd64461.h> |
30 | #include <asm/cpu/dac.h> | 30 | #include <cpu/dac.h> |
31 | 31 | ||
32 | #define WIDTH 640 | 32 | #define WIDTH 640 |
33 | 33 | ||
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 94e4d3ac1a05..ccd986140c95 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/mm.h> | ||
27 | #include <linux/fb.h> | 28 | #include <linux/fb.h> |
28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
29 | #include <linux/init.h> | 30 | #include <linux/init.h> |
@@ -32,9 +33,9 @@ | |||
32 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
33 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
34 | 35 | ||
35 | #include <asm/hardware.h> | 36 | #include <mach/hardware.h> |
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | #include <asm/arch/imxfb.h> | 38 | #include <mach/imxfb.h> |
38 | 39 | ||
39 | /* | 40 | /* |
40 | * Complain if VAR is out of range. | 41 | * Complain if VAR is out of range. |
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index aa8c714d6245..b790ddff76f9 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c | |||
@@ -596,7 +596,7 @@ static struct fb_ops macfb_ops = { | |||
596 | .fb_imageblit = cfb_imageblit, | 596 | .fb_imageblit = cfb_imageblit, |
597 | }; | 597 | }; |
598 | 598 | ||
599 | void __init macfb_setup(char *options) | 599 | static void __init macfb_setup(char *options) |
600 | { | 600 | { |
601 | char *this_opt; | 601 | char *this_opt; |
602 | 602 | ||
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 75ee5a12e549..c14e3e2212b3 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c | |||
@@ -87,13 +87,7 @@ static int matroxfb_gpio_getscl(void* data) { | |||
87 | return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0; | 87 | return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static struct i2c_adapter matrox_i2c_adapter_template = | 90 | static const struct i2c_algo_bit_data matrox_i2c_algo_template = |
91 | { | ||
92 | .owner = THIS_MODULE, | ||
93 | .id = I2C_HW_B_G400, | ||
94 | }; | ||
95 | |||
96 | static struct i2c_algo_bit_data matrox_i2c_algo_template = | ||
97 | { | 91 | { |
98 | .setsda = matroxfb_gpio_setsda, | 92 | .setsda = matroxfb_gpio_setsda, |
99 | .setscl = matroxfb_gpio_setscl, | 93 | .setscl = matroxfb_gpio_setscl, |
@@ -112,7 +106,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, | |||
112 | b->minfo = minfo; | 106 | b->minfo = minfo; |
113 | b->mask.data = data; | 107 | b->mask.data = data; |
114 | b->mask.clock = clock; | 108 | b->mask.clock = clock; |
115 | b->adapter = matrox_i2c_adapter_template; | 109 | b->adapter.owner = THIS_MODULE; |
116 | snprintf(b->adapter.name, sizeof(b->adapter.name), name, | 110 | snprintf(b->adapter.name, sizeof(b->adapter.name), name, |
117 | minfo->fbcon.node); | 111 | minfo->fbcon.node); |
118 | i2c_set_adapdata(&b->adapter, b); | 112 | i2c_set_adapdata(&b->adapter, b); |
@@ -187,6 +181,17 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) { | |||
187 | MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0); | 181 | MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0); |
188 | if (err) | 182 | if (err) |
189 | printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); | 183 | printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); |
184 | else { | ||
185 | struct i2c_board_info maven_info = { | ||
186 | I2C_BOARD_INFO("maven", 0x1b), | ||
187 | }; | ||
188 | unsigned short const addr_list[2] = { | ||
189 | 0x1b, I2C_CLIENT_END | ||
190 | }; | ||
191 | |||
192 | i2c_new_probed_device(&m2info->maven.adapter, | ||
193 | &maven_info, addr_list); | ||
194 | } | ||
190 | } | 195 | } |
191 | return m2info; | 196 | return m2info; |
192 | fail_ddc1:; | 197 | fail_ddc1:; |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 54e82f35353d..c02136202792 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -2536,7 +2536,7 @@ module_param(fh, int, 0); | |||
2536 | MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz"); | 2536 | MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz"); |
2537 | module_param(fv, int, 0); | 2537 | module_param(fv, int, 0); |
2538 | MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n" | 2538 | MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n" |
2539 | "You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n"); | 2539 | "You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\""); |
2540 | module_param(grayscale, int, 0); | 2540 | module_param(grayscale, int, 0); |
2541 | MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)"); | 2541 | MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)"); |
2542 | module_param(cross4MB, int, 0); | 2542 | module_param(cross4MB, int, 0); |
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 89da27bd5c49..042408a8c631 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #include <linux/matroxfb.h> | 19 | #include <linux/matroxfb.h> |
20 | #include <asm/div64.h> | 20 | #include <asm/div64.h> |
21 | 21 | ||
22 | #define MAVEN_I2CID (0x1B) | ||
23 | |||
24 | #define MGATVO_B 1 | 22 | #define MGATVO_B 1 |
25 | #define MGATVO_C 2 | 23 | #define MGATVO_C 2 |
26 | 24 | ||
@@ -128,7 +126,7 @@ static int get_ctrl_id(__u32 v4l2_id) { | |||
128 | 126 | ||
129 | struct maven_data { | 127 | struct maven_data { |
130 | struct matrox_fb_info* primary_head; | 128 | struct matrox_fb_info* primary_head; |
131 | struct i2c_client client; | 129 | struct i2c_client *client; |
132 | int version; | 130 | int version; |
133 | }; | 131 | }; |
134 | 132 | ||
@@ -974,7 +972,7 @@ static inline int maven_compute_timming(struct maven_data* md, | |||
974 | 972 | ||
975 | static int maven_program_timming(struct maven_data* md, | 973 | static int maven_program_timming(struct maven_data* md, |
976 | const struct mavenregs* m) { | 974 | const struct mavenregs* m) { |
977 | struct i2c_client* c = &md->client; | 975 | struct i2c_client *c = md->client; |
978 | 976 | ||
979 | if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { | 977 | if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { |
980 | LR(0x80); | 978 | LR(0x80); |
@@ -1011,7 +1009,7 @@ static int maven_program_timming(struct maven_data* md, | |||
1011 | } | 1009 | } |
1012 | 1010 | ||
1013 | static inline int maven_resync(struct maven_data* md) { | 1011 | static inline int maven_resync(struct maven_data* md) { |
1014 | struct i2c_client* c = &md->client; | 1012 | struct i2c_client *c = md->client; |
1015 | maven_set_reg(c, 0x95, 0x20); /* start whole thing */ | 1013 | maven_set_reg(c, 0x95, 0x20); /* start whole thing */ |
1016 | return 0; | 1014 | return 0; |
1017 | } | 1015 | } |
@@ -1069,48 +1067,48 @@ static int maven_set_control (struct maven_data* md, | |||
1069 | maven_compute_bwlevel(md, &blacklevel, &whitelevel); | 1067 | maven_compute_bwlevel(md, &blacklevel, &whitelevel); |
1070 | blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); | 1068 | blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); |
1071 | whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); | 1069 | whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); |
1072 | maven_set_reg_pair(&md->client, 0x0e, blacklevel); | 1070 | maven_set_reg_pair(md->client, 0x0e, blacklevel); |
1073 | maven_set_reg_pair(&md->client, 0x1e, whitelevel); | 1071 | maven_set_reg_pair(md->client, 0x1e, whitelevel); |
1074 | } | 1072 | } |
1075 | break; | 1073 | break; |
1076 | case V4L2_CID_SATURATION: | 1074 | case V4L2_CID_SATURATION: |
1077 | { | 1075 | { |
1078 | maven_set_reg(&md->client, 0x20, p->value); | 1076 | maven_set_reg(md->client, 0x20, p->value); |
1079 | maven_set_reg(&md->client, 0x22, p->value); | 1077 | maven_set_reg(md->client, 0x22, p->value); |
1080 | } | 1078 | } |
1081 | break; | 1079 | break; |
1082 | case V4L2_CID_HUE: | 1080 | case V4L2_CID_HUE: |
1083 | { | 1081 | { |
1084 | maven_set_reg(&md->client, 0x25, p->value); | 1082 | maven_set_reg(md->client, 0x25, p->value); |
1085 | } | 1083 | } |
1086 | break; | 1084 | break; |
1087 | case V4L2_CID_GAMMA: | 1085 | case V4L2_CID_GAMMA: |
1088 | { | 1086 | { |
1089 | const struct maven_gamma* g; | 1087 | const struct maven_gamma* g; |
1090 | g = maven_compute_gamma(md); | 1088 | g = maven_compute_gamma(md); |
1091 | maven_set_reg(&md->client, 0x83, g->reg83); | 1089 | maven_set_reg(md->client, 0x83, g->reg83); |
1092 | maven_set_reg(&md->client, 0x84, g->reg84); | 1090 | maven_set_reg(md->client, 0x84, g->reg84); |
1093 | maven_set_reg(&md->client, 0x85, g->reg85); | 1091 | maven_set_reg(md->client, 0x85, g->reg85); |
1094 | maven_set_reg(&md->client, 0x86, g->reg86); | 1092 | maven_set_reg(md->client, 0x86, g->reg86); |
1095 | maven_set_reg(&md->client, 0x87, g->reg87); | 1093 | maven_set_reg(md->client, 0x87, g->reg87); |
1096 | maven_set_reg(&md->client, 0x88, g->reg88); | 1094 | maven_set_reg(md->client, 0x88, g->reg88); |
1097 | maven_set_reg(&md->client, 0x89, g->reg89); | 1095 | maven_set_reg(md->client, 0x89, g->reg89); |
1098 | maven_set_reg(&md->client, 0x8a, g->reg8a); | 1096 | maven_set_reg(md->client, 0x8a, g->reg8a); |
1099 | maven_set_reg(&md->client, 0x8b, g->reg8b); | 1097 | maven_set_reg(md->client, 0x8b, g->reg8b); |
1100 | } | 1098 | } |
1101 | break; | 1099 | break; |
1102 | case MATROXFB_CID_TESTOUT: | 1100 | case MATROXFB_CID_TESTOUT: |
1103 | { | 1101 | { |
1104 | unsigned char val | 1102 | unsigned char val |
1105 | = maven_get_reg(&md->client,0x8d); | 1103 | = maven_get_reg(md->client, 0x8d); |
1106 | if (p->value) val |= 0x10; | 1104 | if (p->value) val |= 0x10; |
1107 | else val &= ~0x10; | 1105 | else val &= ~0x10; |
1108 | maven_set_reg(&md->client, 0x8d, val); | 1106 | maven_set_reg(md->client, 0x8d, val); |
1109 | } | 1107 | } |
1110 | break; | 1108 | break; |
1111 | case MATROXFB_CID_DEFLICKER: | 1109 | case MATROXFB_CID_DEFLICKER: |
1112 | { | 1110 | { |
1113 | maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); | 1111 | maven_set_reg(md->client, 0x93, maven_compute_deflicker(md)); |
1114 | } | 1112 | } |
1115 | break; | 1113 | break; |
1116 | } | 1114 | } |
@@ -1189,6 +1187,7 @@ static int maven_init_client(struct i2c_client* clnt) { | |||
1189 | MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); | 1187 | MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); |
1190 | 1188 | ||
1191 | md->primary_head = MINFO; | 1189 | md->primary_head = MINFO; |
1190 | md->client = clnt; | ||
1192 | down_write(&ACCESS_FBINFO(altout.lock)); | 1191 | down_write(&ACCESS_FBINFO(altout.lock)); |
1193 | ACCESS_FBINFO(outputs[1]).output = &maven_altout; | 1192 | ACCESS_FBINFO(outputs[1]).output = &maven_altout; |
1194 | ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; | 1193 | ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; |
@@ -1232,14 +1231,11 @@ static int maven_shutdown_client(struct i2c_client* clnt) { | |||
1232 | return 0; | 1231 | return 0; |
1233 | } | 1232 | } |
1234 | 1233 | ||
1235 | static const unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END }; | 1234 | static int maven_probe(struct i2c_client *client, |
1236 | I2C_CLIENT_INSMOD; | 1235 | const struct i2c_device_id *id) |
1237 | 1236 | { | |
1238 | static struct i2c_driver maven_driver; | 1237 | struct i2c_adapter *adapter = client->adapter; |
1239 | 1238 | int err = -ENODEV; | |
1240 | static int maven_detect_client(struct i2c_adapter* adapter, int address, int kind) { | ||
1241 | int err = 0; | ||
1242 | struct i2c_client* new_client; | ||
1243 | struct maven_data* data; | 1239 | struct maven_data* data; |
1244 | 1240 | ||
1245 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA | | 1241 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA | |
@@ -1250,50 +1246,37 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin | |||
1250 | err = -ENOMEM; | 1246 | err = -ENOMEM; |
1251 | goto ERROR0; | 1247 | goto ERROR0; |
1252 | } | 1248 | } |
1253 | new_client = &data->client; | 1249 | i2c_set_clientdata(client, data); |
1254 | i2c_set_clientdata(new_client, data); | 1250 | err = maven_init_client(client); |
1255 | new_client->addr = address; | ||
1256 | new_client->adapter = adapter; | ||
1257 | new_client->driver = &maven_driver; | ||
1258 | new_client->flags = 0; | ||
1259 | strlcpy(new_client->name, "maven", I2C_NAME_SIZE); | ||
1260 | if ((err = i2c_attach_client(new_client))) | ||
1261 | goto ERROR3; | ||
1262 | err = maven_init_client(new_client); | ||
1263 | if (err) | 1251 | if (err) |
1264 | goto ERROR4; | 1252 | goto ERROR4; |
1265 | return 0; | 1253 | return 0; |
1266 | ERROR4:; | 1254 | ERROR4:; |
1267 | i2c_detach_client(new_client); | 1255 | kfree(data); |
1268 | ERROR3:; | ||
1269 | kfree(new_client); | ||
1270 | ERROR0:; | 1256 | ERROR0:; |
1271 | return err; | 1257 | return err; |
1272 | } | 1258 | } |
1273 | 1259 | ||
1274 | static int maven_attach_adapter(struct i2c_adapter* adapter) { | 1260 | static int maven_remove(struct i2c_client *client) |
1275 | if (adapter->id == I2C_HW_B_G400) | 1261 | { |
1276 | return i2c_probe(adapter, &addr_data, &maven_detect_client); | ||
1277 | return 0; | ||
1278 | } | ||
1279 | |||
1280 | static int maven_detach_client(struct i2c_client* client) { | ||
1281 | int err; | ||
1282 | |||
1283 | if ((err = i2c_detach_client(client))) | ||
1284 | return err; | ||
1285 | maven_shutdown_client(client); | 1262 | maven_shutdown_client(client); |
1286 | kfree(i2c_get_clientdata(client)); | 1263 | kfree(i2c_get_clientdata(client)); |
1287 | return 0; | 1264 | return 0; |
1288 | } | 1265 | } |
1289 | 1266 | ||
1267 | static const struct i2c_device_id maven_id[] = { | ||
1268 | { "maven", 0 }, | ||
1269 | { } | ||
1270 | }; | ||
1271 | MODULE_DEVICE_TABLE(i2c, maven_id); | ||
1272 | |||
1290 | static struct i2c_driver maven_driver={ | 1273 | static struct i2c_driver maven_driver={ |
1291 | .driver = { | 1274 | .driver = { |
1292 | .name = "maven", | 1275 | .name = "maven", |
1293 | }, | 1276 | }, |
1294 | .id = I2C_DRIVERID_MGATVO, | 1277 | .probe = maven_probe, |
1295 | .attach_adapter = maven_attach_adapter, | 1278 | .remove = maven_remove, |
1296 | .detach_client = maven_detach_client, | 1279 | .id_table = maven_id, |
1297 | }; | 1280 | }; |
1298 | 1281 | ||
1299 | static int __init matroxfb_maven_init(void) | 1282 | static int __init matroxfb_maven_init(void) |
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 5246b0402d76..25172b2a2a94 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -201,7 +201,6 @@ static int neoFindMode(int xres, int yres, int depth) | |||
201 | * | 201 | * |
202 | * Determine the closest clock frequency to the one requested. | 202 | * Determine the closest clock frequency to the one requested. |
203 | */ | 203 | */ |
204 | #define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */ | ||
205 | #define MAX_N 127 | 204 | #define MAX_N 127 |
206 | #define MAX_D 31 | 205 | #define MAX_D 31 |
207 | #define MAX_F 1 | 206 | #define MAX_F 1 |
@@ -211,27 +210,24 @@ static void neoCalcVCLK(const struct fb_info *info, | |||
211 | { | 210 | { |
212 | int n, d, f; | 211 | int n, d, f; |
213 | int n_best = 0, d_best = 0, f_best = 0; | 212 | int n_best = 0, d_best = 0, f_best = 0; |
214 | long f_best_diff = (0x7ffff << 12); /* 20.12 */ | 213 | long f_best_diff = 0x7ffff; |
215 | long f_target = (freq << 12) / 1000; /* 20.12 */ | ||
216 | 214 | ||
217 | for (f = 0; f <= MAX_F; f++) | 215 | for (f = 0; f <= MAX_F; f++) |
218 | for (n = 0; n <= MAX_N; n++) | 216 | for (d = 0; d <= MAX_D; d++) |
219 | for (d = 0; d <= MAX_D; d++) { | 217 | for (n = 0; n <= MAX_N; n++) { |
220 | long f_out; /* 20.12 */ | 218 | long f_out; |
221 | long f_diff; /* 20.12 */ | 219 | long f_diff; |
222 | 220 | ||
223 | f_out = | 221 | f_out = ((14318 * (n + 1)) / (d + 1)) >> f; |
224 | ((((n + 1) << 12) / ((d + | 222 | f_diff = abs(f_out - freq); |
225 | 1) * | 223 | if (f_diff <= f_best_diff) { |
226 | (1 << f))) >> 12) | ||
227 | * REF_FREQ; | ||
228 | f_diff = abs(f_out - f_target); | ||
229 | if (f_diff < f_best_diff) { | ||
230 | f_best_diff = f_diff; | 224 | f_best_diff = f_diff; |
231 | n_best = n; | 225 | n_best = n; |
232 | d_best = d; | 226 | d_best = d; |
233 | f_best = f; | 227 | f_best = f; |
234 | } | 228 | } |
229 | if (f_out > freq) | ||
230 | break; | ||
235 | } | 231 | } |
236 | 232 | ||
237 | if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 || | 233 | if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 || |
@@ -248,11 +244,11 @@ static void neoCalcVCLK(const struct fb_info *info, | |||
248 | par->VCLK3Denominator = d_best; | 244 | par->VCLK3Denominator = d_best; |
249 | 245 | ||
250 | #ifdef NEOFB_DEBUG | 246 | #ifdef NEOFB_DEBUG |
251 | printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n", | 247 | printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n", |
252 | f_target >> 12, | 248 | freq, |
253 | par->VCLK3NumeratorLow, | 249 | par->VCLK3NumeratorLow, |
254 | par->VCLK3NumeratorHigh, | 250 | par->VCLK3NumeratorHigh, |
255 | par->VCLK3Denominator, f_best_diff >> 12); | 251 | par->VCLK3Denominator, f_best_diff); |
256 | #endif | 252 | #endif |
257 | } | 253 | } |
258 | 254 | ||
@@ -263,15 +259,20 @@ static void neoCalcVCLK(const struct fb_info *info, | |||
263 | */ | 259 | */ |
264 | 260 | ||
265 | static int vgaHWInit(const struct fb_var_screeninfo *var, | 261 | static int vgaHWInit(const struct fb_var_screeninfo *var, |
266 | const struct fb_info *info, | 262 | struct neofb_par *par) |
267 | struct neofb_par *par, struct xtimings *timings) | ||
268 | { | 263 | { |
264 | int hsync_end = var->xres + var->right_margin + var->hsync_len; | ||
265 | int htotal = (hsync_end + var->left_margin) >> 3; | ||
266 | int vsync_start = var->yres + var->lower_margin; | ||
267 | int vsync_end = vsync_start + var->vsync_len; | ||
268 | int vtotal = vsync_end + var->upper_margin; | ||
269 | |||
269 | par->MiscOutReg = 0x23; | 270 | par->MiscOutReg = 0x23; |
270 | 271 | ||
271 | if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT)) | 272 | if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) |
272 | par->MiscOutReg |= 0x40; | 273 | par->MiscOutReg |= 0x40; |
273 | 274 | ||
274 | if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT)) | 275 | if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) |
275 | par->MiscOutReg |= 0x80; | 276 | par->MiscOutReg |= 0x80; |
276 | 277 | ||
277 | /* | 278 | /* |
@@ -286,25 +287,25 @@ static int vgaHWInit(const struct fb_var_screeninfo *var, | |||
286 | /* | 287 | /* |
287 | * CRTC Controller | 288 | * CRTC Controller |
288 | */ | 289 | */ |
289 | par->CRTC[0] = (timings->HTotal >> 3) - 5; | 290 | par->CRTC[0] = htotal - 5; |
290 | par->CRTC[1] = (timings->HDisplay >> 3) - 1; | 291 | par->CRTC[1] = (var->xres >> 3) - 1; |
291 | par->CRTC[2] = (timings->HDisplay >> 3) - 1; | 292 | par->CRTC[2] = (var->xres >> 3) - 1; |
292 | par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80; | 293 | par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80; |
293 | par->CRTC[4] = (timings->HSyncStart >> 3); | 294 | par->CRTC[4] = ((var->xres + var->right_margin) >> 3); |
294 | par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2) | 295 | par->CRTC[5] = (((htotal - 1) & 0x20) << 2) |
295 | | (((timings->HSyncEnd >> 3)) & 0x1F); | 296 | | (((hsync_end >> 3)) & 0x1F); |
296 | par->CRTC[6] = (timings->VTotal - 2) & 0xFF; | 297 | par->CRTC[6] = (vtotal - 2) & 0xFF; |
297 | par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8) | 298 | par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8) |
298 | | (((timings->VDisplay - 1) & 0x100) >> 7) | 299 | | (((var->yres - 1) & 0x100) >> 7) |
299 | | ((timings->VSyncStart & 0x100) >> 6) | 300 | | ((vsync_start & 0x100) >> 6) |
300 | | (((timings->VDisplay - 1) & 0x100) >> 5) | 301 | | (((var->yres - 1) & 0x100) >> 5) |
301 | | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4) | 302 | | 0x10 | (((vtotal - 2) & 0x200) >> 4) |
302 | | (((timings->VDisplay - 1) & 0x200) >> 3) | 303 | | (((var->yres - 1) & 0x200) >> 3) |
303 | | ((timings->VSyncStart & 0x200) >> 2); | 304 | | ((vsync_start & 0x200) >> 2); |
304 | par->CRTC[8] = 0x00; | 305 | par->CRTC[8] = 0x00; |
305 | par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40; | 306 | par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40; |
306 | 307 | ||
307 | if (timings->dblscan) | 308 | if (var->vmode & FB_VMODE_DOUBLE) |
308 | par->CRTC[9] |= 0x80; | 309 | par->CRTC[9] |= 0x80; |
309 | 310 | ||
310 | par->CRTC[10] = 0x00; | 311 | par->CRTC[10] = 0x00; |
@@ -313,13 +314,13 @@ static int vgaHWInit(const struct fb_var_screeninfo *var, | |||
313 | par->CRTC[13] = 0x00; | 314 | par->CRTC[13] = 0x00; |
314 | par->CRTC[14] = 0x00; | 315 | par->CRTC[14] = 0x00; |
315 | par->CRTC[15] = 0x00; | 316 | par->CRTC[15] = 0x00; |
316 | par->CRTC[16] = timings->VSyncStart & 0xFF; | 317 | par->CRTC[16] = vsync_start & 0xFF; |
317 | par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20; | 318 | par->CRTC[17] = (vsync_end & 0x0F) | 0x20; |
318 | par->CRTC[18] = (timings->VDisplay - 1) & 0xFF; | 319 | par->CRTC[18] = (var->yres - 1) & 0xFF; |
319 | par->CRTC[19] = var->xres_virtual >> 4; | 320 | par->CRTC[19] = var->xres_virtual >> 4; |
320 | par->CRTC[20] = 0x00; | 321 | par->CRTC[20] = 0x00; |
321 | par->CRTC[21] = (timings->VDisplay - 1) & 0xFF; | 322 | par->CRTC[21] = (var->yres - 1) & 0xFF; |
322 | par->CRTC[22] = (timings->VTotal - 1) & 0xFF; | 323 | par->CRTC[22] = (vtotal - 1) & 0xFF; |
323 | par->CRTC[23] = 0xC3; | 324 | par->CRTC[23] = 0xC3; |
324 | par->CRTC[24] = 0xFF; | 325 | par->CRTC[24] = 0xFF; |
325 | 326 | ||
@@ -483,7 +484,8 @@ static inline int neo2200_sync(struct fb_info *info) | |||
483 | { | 484 | { |
484 | struct neofb_par *par = info->par; | 485 | struct neofb_par *par = info->par; |
485 | 486 | ||
486 | while (readl(&par->neo2200->bltStat) & 1); | 487 | while (readl(&par->neo2200->bltStat) & 1) |
488 | cpu_relax(); | ||
487 | return 0; | 489 | return 0; |
488 | } | 490 | } |
489 | 491 | ||
@@ -591,34 +593,14 @@ static int | |||
591 | neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 593 | neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
592 | { | 594 | { |
593 | struct neofb_par *par = info->par; | 595 | struct neofb_par *par = info->par; |
594 | unsigned int pixclock = var->pixclock; | ||
595 | struct xtimings timings; | ||
596 | int memlen, vramlen; | 596 | int memlen, vramlen; |
597 | int mode_ok = 0; | 597 | int mode_ok = 0; |
598 | 598 | ||
599 | DBG("neofb_check_var"); | 599 | DBG("neofb_check_var"); |
600 | 600 | ||
601 | if (!pixclock) | 601 | if (PICOS2KHZ(var->pixclock) > par->maxClock) |
602 | pixclock = 10000; /* 10ns = 100MHz */ | ||
603 | timings.pixclock = 1000000000 / pixclock; | ||
604 | if (timings.pixclock < 1) | ||
605 | timings.pixclock = 1; | ||
606 | |||
607 | if (timings.pixclock > par->maxClock) | ||
608 | return -EINVAL; | 602 | return -EINVAL; |
609 | 603 | ||
610 | timings.dblscan = var->vmode & FB_VMODE_DOUBLE; | ||
611 | timings.interlaced = var->vmode & FB_VMODE_INTERLACED; | ||
612 | timings.HDisplay = var->xres; | ||
613 | timings.HSyncStart = timings.HDisplay + var->right_margin; | ||
614 | timings.HSyncEnd = timings.HSyncStart + var->hsync_len; | ||
615 | timings.HTotal = timings.HSyncEnd + var->left_margin; | ||
616 | timings.VDisplay = var->yres; | ||
617 | timings.VSyncStart = timings.VDisplay + var->lower_margin; | ||
618 | timings.VSyncEnd = timings.VSyncStart + var->vsync_len; | ||
619 | timings.VTotal = timings.VSyncEnd + var->upper_margin; | ||
620 | timings.sync = var->sync; | ||
621 | |||
622 | /* Is the mode larger than the LCD panel? */ | 604 | /* Is the mode larger than the LCD panel? */ |
623 | if (par->internal_display && | 605 | if (par->internal_display && |
624 | ((var->xres > par->NeoPanelWidth) || | 606 | ((var->xres > par->NeoPanelWidth) || |
@@ -759,11 +741,11 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
759 | static int neofb_set_par(struct fb_info *info) | 741 | static int neofb_set_par(struct fb_info *info) |
760 | { | 742 | { |
761 | struct neofb_par *par = info->par; | 743 | struct neofb_par *par = info->par; |
762 | struct xtimings timings; | ||
763 | unsigned char temp; | 744 | unsigned char temp; |
764 | int i, clock_hi = 0; | 745 | int i, clock_hi = 0; |
765 | int lcd_stretch; | 746 | int lcd_stretch; |
766 | int hoffset, voffset; | 747 | int hoffset, voffset; |
748 | int vsync_start, vtotal; | ||
767 | 749 | ||
768 | DBG("neofb_set_par"); | 750 | DBG("neofb_set_par"); |
769 | 751 | ||
@@ -771,28 +753,15 @@ static int neofb_set_par(struct fb_info *info) | |||
771 | 753 | ||
772 | vgaHWProtect(1); /* Blank the screen */ | 754 | vgaHWProtect(1); /* Blank the screen */ |
773 | 755 | ||
774 | timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE; | 756 | vsync_start = info->var.yres + info->var.lower_margin; |
775 | timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED; | 757 | vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin; |
776 | timings.HDisplay = info->var.xres; | ||
777 | timings.HSyncStart = timings.HDisplay + info->var.right_margin; | ||
778 | timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len; | ||
779 | timings.HTotal = timings.HSyncEnd + info->var.left_margin; | ||
780 | timings.VDisplay = info->var.yres; | ||
781 | timings.VSyncStart = timings.VDisplay + info->var.lower_margin; | ||
782 | timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len; | ||
783 | timings.VTotal = timings.VSyncEnd + info->var.upper_margin; | ||
784 | timings.sync = info->var.sync; | ||
785 | timings.pixclock = PICOS2KHZ(info->var.pixclock); | ||
786 | |||
787 | if (timings.pixclock < 1) | ||
788 | timings.pixclock = 1; | ||
789 | 758 | ||
790 | /* | 759 | /* |
791 | * This will allocate the datastructure and initialize all of the | 760 | * This will allocate the datastructure and initialize all of the |
792 | * generic VGA registers. | 761 | * generic VGA registers. |
793 | */ | 762 | */ |
794 | 763 | ||
795 | if (vgaHWInit(&info->var, info, par, &timings)) | 764 | if (vgaHWInit(&info->var, par)) |
796 | return -EINVAL; | 765 | return -EINVAL; |
797 | 766 | ||
798 | /* | 767 | /* |
@@ -831,10 +800,10 @@ static int neofb_set_par(struct fb_info *info) | |||
831 | par->ExtCRTDispAddr = 0x10; | 800 | par->ExtCRTDispAddr = 0x10; |
832 | 801 | ||
833 | /* Vertical Extension */ | 802 | /* Vertical Extension */ |
834 | par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10) | 803 | par->VerticalExt = (((vtotal - 2) & 0x400) >> 10) |
835 | | (((timings.VDisplay - 1) & 0x400) >> 9) | 804 | | (((info->var.yres - 1) & 0x400) >> 9) |
836 | | (((timings.VSyncStart) & 0x400) >> 8) | 805 | | (((vsync_start) & 0x400) >> 8) |
837 | | (((timings.VSyncStart) & 0x400) >> 7); | 806 | | (((vsync_start) & 0x400) >> 7); |
838 | 807 | ||
839 | /* Fast write bursts on unless disabled. */ | 808 | /* Fast write bursts on unless disabled. */ |
840 | if (par->pci_burst) | 809 | if (par->pci_burst) |
@@ -995,7 +964,7 @@ static int neofb_set_par(struct fb_info *info) | |||
995 | * Calculate the VCLK that most closely matches the requested dot | 964 | * Calculate the VCLK that most closely matches the requested dot |
996 | * clock. | 965 | * clock. |
997 | */ | 966 | */ |
998 | neoCalcVCLK(info, par, timings.pixclock); | 967 | neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock)); |
999 | 968 | ||
1000 | /* Since we program the clocks ourselves, always use VCLK3. */ | 969 | /* Since we program the clocks ourselves, always use VCLK3. */ |
1001 | par->MiscOutReg |= 0x0C; | 970 | par->MiscOutReg |= 0x0C; |
@@ -1927,9 +1896,6 @@ static int __devinit neo_init_hw(struct fb_info *info) | |||
1927 | int maxClock = 65000; | 1896 | int maxClock = 65000; |
1928 | int CursorMem = 1024; | 1897 | int CursorMem = 1024; |
1929 | int CursorOff = 0x100; | 1898 | int CursorOff = 0x100; |
1930 | int linearSize = 1024; | ||
1931 | int maxWidth = 1024; | ||
1932 | int maxHeight = 1024; | ||
1933 | 1899 | ||
1934 | DBG("neo_init_hw"); | 1900 | DBG("neo_init_hw"); |
1935 | 1901 | ||
@@ -1948,81 +1914,52 @@ static int __devinit neo_init_hw(struct fb_info *info) | |||
1948 | case FB_ACCEL_NEOMAGIC_NM2070: | 1914 | case FB_ACCEL_NEOMAGIC_NM2070: |
1949 | videoRam = 896; | 1915 | videoRam = 896; |
1950 | maxClock = 65000; | 1916 | maxClock = 65000; |
1951 | CursorMem = 2048; | ||
1952 | CursorOff = 0x100; | ||
1953 | linearSize = 1024; | ||
1954 | maxWidth = 1024; | ||
1955 | maxHeight = 1024; | ||
1956 | break; | 1917 | break; |
1957 | case FB_ACCEL_NEOMAGIC_NM2090: | 1918 | case FB_ACCEL_NEOMAGIC_NM2090: |
1958 | case FB_ACCEL_NEOMAGIC_NM2093: | 1919 | case FB_ACCEL_NEOMAGIC_NM2093: |
1959 | videoRam = 1152; | ||
1960 | maxClock = 80000; | ||
1961 | CursorMem = 2048; | ||
1962 | CursorOff = 0x100; | ||
1963 | linearSize = 2048; | ||
1964 | maxWidth = 1024; | ||
1965 | maxHeight = 1024; | ||
1966 | break; | ||
1967 | case FB_ACCEL_NEOMAGIC_NM2097: | 1920 | case FB_ACCEL_NEOMAGIC_NM2097: |
1968 | videoRam = 1152; | 1921 | videoRam = 1152; |
1969 | maxClock = 80000; | 1922 | maxClock = 80000; |
1970 | CursorMem = 1024; | ||
1971 | CursorOff = 0x100; | ||
1972 | linearSize = 2048; | ||
1973 | maxWidth = 1024; | ||
1974 | maxHeight = 1024; | ||
1975 | break; | 1923 | break; |
1976 | case FB_ACCEL_NEOMAGIC_NM2160: | 1924 | case FB_ACCEL_NEOMAGIC_NM2160: |
1977 | videoRam = 2048; | 1925 | videoRam = 2048; |
1978 | maxClock = 90000; | 1926 | maxClock = 90000; |
1979 | CursorMem = 1024; | ||
1980 | CursorOff = 0x100; | ||
1981 | linearSize = 2048; | ||
1982 | maxWidth = 1024; | ||
1983 | maxHeight = 1024; | ||
1984 | break; | 1927 | break; |
1985 | case FB_ACCEL_NEOMAGIC_NM2200: | 1928 | case FB_ACCEL_NEOMAGIC_NM2200: |
1986 | videoRam = 2560; | 1929 | videoRam = 2560; |
1987 | maxClock = 110000; | 1930 | maxClock = 110000; |
1988 | CursorMem = 1024; | ||
1989 | CursorOff = 0x1000; | ||
1990 | linearSize = 4096; | ||
1991 | maxWidth = 1280; | ||
1992 | maxHeight = 1024; /* ???? */ | ||
1993 | |||
1994 | par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; | ||
1995 | break; | 1931 | break; |
1996 | case FB_ACCEL_NEOMAGIC_NM2230: | 1932 | case FB_ACCEL_NEOMAGIC_NM2230: |
1997 | videoRam = 3008; | 1933 | videoRam = 3008; |
1998 | maxClock = 110000; | 1934 | maxClock = 110000; |
1999 | CursorMem = 1024; | ||
2000 | CursorOff = 0x1000; | ||
2001 | linearSize = 4096; | ||
2002 | maxWidth = 1280; | ||
2003 | maxHeight = 1024; /* ???? */ | ||
2004 | |||
2005 | par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; | ||
2006 | break; | 1935 | break; |
2007 | case FB_ACCEL_NEOMAGIC_NM2360: | 1936 | case FB_ACCEL_NEOMAGIC_NM2360: |
2008 | videoRam = 4096; | 1937 | videoRam = 4096; |
2009 | maxClock = 110000; | 1938 | maxClock = 110000; |
2010 | CursorMem = 1024; | ||
2011 | CursorOff = 0x1000; | ||
2012 | linearSize = 4096; | ||
2013 | maxWidth = 1280; | ||
2014 | maxHeight = 1024; /* ???? */ | ||
2015 | |||
2016 | par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; | ||
2017 | break; | 1939 | break; |
2018 | case FB_ACCEL_NEOMAGIC_NM2380: | 1940 | case FB_ACCEL_NEOMAGIC_NM2380: |
2019 | videoRam = 6144; | 1941 | videoRam = 6144; |
2020 | maxClock = 110000; | 1942 | maxClock = 110000; |
1943 | break; | ||
1944 | } | ||
1945 | switch (info->fix.accel) { | ||
1946 | case FB_ACCEL_NEOMAGIC_NM2070: | ||
1947 | case FB_ACCEL_NEOMAGIC_NM2090: | ||
1948 | case FB_ACCEL_NEOMAGIC_NM2093: | ||
1949 | CursorMem = 2048; | ||
1950 | CursorOff = 0x100; | ||
1951 | break; | ||
1952 | case FB_ACCEL_NEOMAGIC_NM2097: | ||
1953 | case FB_ACCEL_NEOMAGIC_NM2160: | ||
1954 | CursorMem = 1024; | ||
1955 | CursorOff = 0x100; | ||
1956 | break; | ||
1957 | case FB_ACCEL_NEOMAGIC_NM2200: | ||
1958 | case FB_ACCEL_NEOMAGIC_NM2230: | ||
1959 | case FB_ACCEL_NEOMAGIC_NM2360: | ||
1960 | case FB_ACCEL_NEOMAGIC_NM2380: | ||
2021 | CursorMem = 1024; | 1961 | CursorMem = 1024; |
2022 | CursorOff = 0x1000; | 1962 | CursorOff = 0x1000; |
2023 | linearSize = 8192; | ||
2024 | maxWidth = 1280; | ||
2025 | maxHeight = 1024; /* ???? */ | ||
2026 | 1963 | ||
2027 | par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; | 1964 | par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; |
2028 | break; | 1965 | break; |
@@ -2036,7 +1973,7 @@ static int __devinit neo_init_hw(struct fb_info *info) | |||
2036 | */ | 1973 | */ |
2037 | par->maxClock = maxClock; | 1974 | par->maxClock = maxClock; |
2038 | par->cursorOff = CursorOff; | 1975 | par->cursorOff = CursorOff; |
2039 | return ((videoRam * 1024)); | 1976 | return videoRam * 1024; |
2040 | } | 1977 | } |
2041 | 1978 | ||
2042 | 1979 | ||
diff --git a/drivers/video/offb.c b/drivers/video/offb.c index d7b3dcc0dc43..e1d9eeb1aeaf 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c | |||
@@ -47,6 +47,7 @@ enum { | |||
47 | cmap_M3B, /* ATI Rage Mobility M3 Head B */ | 47 | cmap_M3B, /* ATI Rage Mobility M3 Head B */ |
48 | cmap_radeon, /* ATI Radeon */ | 48 | cmap_radeon, /* ATI Radeon */ |
49 | cmap_gxt2000, /* IBM GXT2000 */ | 49 | cmap_gxt2000, /* IBM GXT2000 */ |
50 | cmap_avivo, /* ATI R5xx */ | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | struct offb_par { | 53 | struct offb_par { |
@@ -58,26 +59,36 @@ struct offb_par { | |||
58 | 59 | ||
59 | struct offb_par default_par; | 60 | struct offb_par default_par; |
60 | 61 | ||
61 | /* | ||
62 | * Interface used by the world | ||
63 | */ | ||
64 | |||
65 | static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
66 | u_int transp, struct fb_info *info); | ||
67 | static int offb_blank(int blank, struct fb_info *info); | ||
68 | |||
69 | #ifdef CONFIG_PPC32 | 62 | #ifdef CONFIG_PPC32 |
70 | extern boot_infos_t *boot_infos; | 63 | extern boot_infos_t *boot_infos; |
71 | #endif | 64 | #endif |
72 | 65 | ||
73 | static struct fb_ops offb_ops = { | 66 | /* Definitions used by the Avivo palette hack */ |
74 | .owner = THIS_MODULE, | 67 | #define AVIVO_DC_LUT_RW_SELECT 0x6480 |
75 | .fb_setcolreg = offb_setcolreg, | 68 | #define AVIVO_DC_LUT_RW_MODE 0x6484 |
76 | .fb_blank = offb_blank, | 69 | #define AVIVO_DC_LUT_RW_INDEX 0x6488 |
77 | .fb_fillrect = cfb_fillrect, | 70 | #define AVIVO_DC_LUT_SEQ_COLOR 0x648c |
78 | .fb_copyarea = cfb_copyarea, | 71 | #define AVIVO_DC_LUT_PWL_DATA 0x6490 |
79 | .fb_imageblit = cfb_imageblit, | 72 | #define AVIVO_DC_LUT_30_COLOR 0x6494 |
80 | }; | 73 | #define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498 |
74 | #define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c | ||
75 | #define AVIVO_DC_LUT_AUTOFILL 0x64a0 | ||
76 | |||
77 | #define AVIVO_DC_LUTA_CONTROL 0x64c0 | ||
78 | #define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4 | ||
79 | #define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8 | ||
80 | #define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc | ||
81 | #define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0 | ||
82 | #define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4 | ||
83 | #define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8 | ||
84 | |||
85 | #define AVIVO_DC_LUTB_CONTROL 0x6cc0 | ||
86 | #define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4 | ||
87 | #define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8 | ||
88 | #define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc | ||
89 | #define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0 | ||
90 | #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4 | ||
91 | #define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8 | ||
81 | 92 | ||
82 | /* | 93 | /* |
83 | * Set a single color register. The values supplied are already | 94 | * Set a single color register. The values supplied are already |
@@ -160,6 +171,17 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
160 | out_le32(((unsigned __iomem *) par->cmap_adr) + regno, | 171 | out_le32(((unsigned __iomem *) par->cmap_adr) + regno, |
161 | (red << 16 | green << 8 | blue)); | 172 | (red << 16 | green << 8 | blue)); |
162 | break; | 173 | break; |
174 | case cmap_avivo: | ||
175 | /* Write to both LUTs for now */ | ||
176 | writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT); | ||
177 | writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX); | ||
178 | writel(((red) << 22) | ((green) << 12) | ((blue) << 2), | ||
179 | par->cmap_adr + AVIVO_DC_LUT_30_COLOR); | ||
180 | writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT); | ||
181 | writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX); | ||
182 | writel(((red) << 22) | ((green) << 12) | ((blue) << 2), | ||
183 | par->cmap_adr + AVIVO_DC_LUT_30_COLOR); | ||
184 | break; | ||
163 | } | 185 | } |
164 | 186 | ||
165 | return 0; | 187 | return 0; |
@@ -216,12 +238,59 @@ static int offb_blank(int blank, struct fb_info *info) | |||
216 | out_le32(((unsigned __iomem *) par->cmap_adr) + i, | 238 | out_le32(((unsigned __iomem *) par->cmap_adr) + i, |
217 | 0); | 239 | 0); |
218 | break; | 240 | break; |
241 | case cmap_avivo: | ||
242 | writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT); | ||
243 | writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX); | ||
244 | writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR); | ||
245 | writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT); | ||
246 | writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX); | ||
247 | writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR); | ||
248 | break; | ||
219 | } | 249 | } |
220 | } else | 250 | } else |
221 | fb_set_cmap(&info->cmap, info); | 251 | fb_set_cmap(&info->cmap, info); |
222 | return 0; | 252 | return 0; |
223 | } | 253 | } |
224 | 254 | ||
255 | static int offb_set_par(struct fb_info *info) | ||
256 | { | ||
257 | struct offb_par *par = (struct offb_par *) info->par; | ||
258 | |||
259 | /* On avivo, initialize palette control */ | ||
260 | if (par->cmap_type == cmap_avivo) { | ||
261 | writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL); | ||
262 | writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE); | ||
263 | writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN); | ||
264 | writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED); | ||
265 | writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE); | ||
266 | writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN); | ||
267 | writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED); | ||
268 | writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL); | ||
269 | writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE); | ||
270 | writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN); | ||
271 | writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED); | ||
272 | writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE); | ||
273 | writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN); | ||
274 | writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED); | ||
275 | writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT); | ||
276 | writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE); | ||
277 | writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK); | ||
278 | writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT); | ||
279 | writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE); | ||
280 | writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK); | ||
281 | } | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static struct fb_ops offb_ops = { | ||
286 | .owner = THIS_MODULE, | ||
287 | .fb_setcolreg = offb_setcolreg, | ||
288 | .fb_set_par = offb_set_par, | ||
289 | .fb_blank = offb_blank, | ||
290 | .fb_fillrect = cfb_fillrect, | ||
291 | .fb_copyarea = cfb_copyarea, | ||
292 | .fb_imageblit = cfb_imageblit, | ||
293 | }; | ||
225 | 294 | ||
226 | static void __iomem *offb_map_reg(struct device_node *np, int index, | 295 | static void __iomem *offb_map_reg(struct device_node *np, int index, |
227 | unsigned long offset, unsigned long size) | 296 | unsigned long offset, unsigned long size) |
@@ -245,6 +314,59 @@ static void __iomem *offb_map_reg(struct device_node *np, int index, | |||
245 | return ioremap(taddr + offset, size); | 314 | return ioremap(taddr + offset, size); |
246 | } | 315 | } |
247 | 316 | ||
317 | static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp, | ||
318 | const char *name, unsigned long address) | ||
319 | { | ||
320 | struct offb_par *par = (struct offb_par *) info->par; | ||
321 | |||
322 | if (dp && !strncmp(name, "ATY,Rage128", 11)) { | ||
323 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); | ||
324 | if (par->cmap_adr) | ||
325 | par->cmap_type = cmap_r128; | ||
326 | } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) | ||
327 | || !strncmp(name, "ATY,RageM3p12A", 14))) { | ||
328 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); | ||
329 | if (par->cmap_adr) | ||
330 | par->cmap_type = cmap_M3A; | ||
331 | } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { | ||
332 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); | ||
333 | if (par->cmap_adr) | ||
334 | par->cmap_type = cmap_M3B; | ||
335 | } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { | ||
336 | par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); | ||
337 | if (par->cmap_adr) | ||
338 | par->cmap_type = cmap_radeon; | ||
339 | } else if (!strncmp(name, "ATY,", 4)) { | ||
340 | unsigned long base = address & 0xff000000UL; | ||
341 | par->cmap_adr = | ||
342 | ioremap(base + 0x7ff000, 0x1000) + 0xcc0; | ||
343 | par->cmap_data = par->cmap_adr + 1; | ||
344 | par->cmap_type = cmap_m64; | ||
345 | } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") || | ||
346 | of_device_is_compatible(dp, "pci1014,21c"))) { | ||
347 | par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); | ||
348 | if (par->cmap_adr) | ||
349 | par->cmap_type = cmap_gxt2000; | ||
350 | } else if (dp && !strncmp(name, "vga,Display-", 12)) { | ||
351 | /* Look for AVIVO initialized by SLOF */ | ||
352 | struct device_node *pciparent = of_get_parent(dp); | ||
353 | const u32 *vid, *did; | ||
354 | vid = of_get_property(pciparent, "vendor-id", NULL); | ||
355 | did = of_get_property(pciparent, "device-id", NULL); | ||
356 | /* This will match most R5xx */ | ||
357 | if (vid && did && *vid == 0x1002 && | ||
358 | ((*did >= 0x7100 && *did < 0x7800) || | ||
359 | (*did >= 0x9400))) { | ||
360 | par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000); | ||
361 | if (par->cmap_adr) | ||
362 | par->cmap_type = cmap_avivo; | ||
363 | } | ||
364 | of_node_put(pciparent); | ||
365 | } | ||
366 | info->fix.visual = (par->cmap_type != cmap_unknown) ? | ||
367 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; | ||
368 | } | ||
369 | |||
248 | static void __init offb_init_fb(const char *name, const char *full_name, | 370 | static void __init offb_init_fb(const char *name, const char *full_name, |
249 | int width, int height, int depth, | 371 | int width, int height, int depth, |
250 | int pitch, unsigned long address, | 372 | int pitch, unsigned long address, |
@@ -283,6 +405,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
283 | 405 | ||
284 | fix = &info->fix; | 406 | fix = &info->fix; |
285 | var = &info->var; | 407 | var = &info->var; |
408 | info->par = par; | ||
286 | 409 | ||
287 | strcpy(fix->id, "OFfb "); | 410 | strcpy(fix->id, "OFfb "); |
288 | strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb ")); | 411 | strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb ")); |
@@ -298,39 +421,9 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
298 | fix->type_aux = 0; | 421 | fix->type_aux = 0; |
299 | 422 | ||
300 | par->cmap_type = cmap_unknown; | 423 | par->cmap_type = cmap_unknown; |
301 | if (depth == 8) { | 424 | if (depth == 8) |
302 | if (dp && !strncmp(name, "ATY,Rage128", 11)) { | 425 | offb_init_palette_hacks(info, dp, name, address); |
303 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); | 426 | else |
304 | if (par->cmap_adr) | ||
305 | par->cmap_type = cmap_r128; | ||
306 | } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) | ||
307 | || !strncmp(name, "ATY,RageM3p12A", 14))) { | ||
308 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); | ||
309 | if (par->cmap_adr) | ||
310 | par->cmap_type = cmap_M3A; | ||
311 | } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { | ||
312 | par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); | ||
313 | if (par->cmap_adr) | ||
314 | par->cmap_type = cmap_M3B; | ||
315 | } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { | ||
316 | par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); | ||
317 | if (par->cmap_adr) | ||
318 | par->cmap_type = cmap_radeon; | ||
319 | } else if (!strncmp(name, "ATY,", 4)) { | ||
320 | unsigned long base = address & 0xff000000UL; | ||
321 | par->cmap_adr = | ||
322 | ioremap(base + 0x7ff000, 0x1000) + 0xcc0; | ||
323 | par->cmap_data = par->cmap_adr + 1; | ||
324 | par->cmap_type = cmap_m64; | ||
325 | } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") || | ||
326 | of_device_is_compatible(dp, "pci1014,21c"))) { | ||
327 | par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); | ||
328 | if (par->cmap_adr) | ||
329 | par->cmap_type = cmap_gxt2000; | ||
330 | } | ||
331 | fix->visual = (par->cmap_type != cmap_unknown) ? | ||
332 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; | ||
333 | } else | ||
334 | fix->visual = FB_VISUAL_TRUECOLOR; | 427 | fix->visual = FB_VISUAL_TRUECOLOR; |
335 | 428 | ||
336 | var->xoffset = var->yoffset = 0; | 429 | var->xoffset = var->yoffset = 0; |
@@ -395,7 +488,6 @@ static void __init offb_init_fb(const char *name, const char *full_name, | |||
395 | 488 | ||
396 | info->fbops = &offb_ops; | 489 | info->fbops = &offb_ops; |
397 | info->screen_base = ioremap(address, fix->smem_len); | 490 | info->screen_base = ioremap(address, fix->smem_len); |
398 | info->par = par; | ||
399 | info->pseudo_palette = (void *) (info + 1); | 491 | info->pseudo_palette = (void *) (info + 1); |
400 | info->flags = FBINFO_DEFAULT | foreign_endian; | 492 | info->flags = FBINFO_DEFAULT | foreign_endian; |
401 | 493 | ||
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c index 4d8ad9cd0e19..9dfcf39d3367 100644 --- a/drivers/video/omap/blizzard.c +++ b/drivers/video/omap/blizzard.c | |||
@@ -26,9 +26,9 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | 28 | ||
29 | #include <asm/arch/dma.h> | 29 | #include <mach/dma.h> |
30 | #include <asm/arch/omapfb.h> | 30 | #include <mach/omapfb.h> |
31 | #include <asm/arch/blizzard.h> | 31 | #include <mach/blizzard.h> |
32 | 32 | ||
33 | #include "dispc.h" | 33 | #include "dispc.h" |
34 | 34 | ||
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index ab32ceb06178..6efcf89e7fbe 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c | |||
@@ -20,13 +20,14 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
23 | #include <linux/mm.h> | ||
23 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
24 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
25 | #include <linux/io.h> | 26 | #include <linux/io.h> |
26 | 27 | ||
27 | #include <asm/arch/sram.h> | 28 | #include <mach/sram.h> |
28 | #include <asm/arch/omapfb.h> | 29 | #include <mach/omapfb.h> |
29 | #include <asm/arch/board.h> | 30 | #include <mach/board.h> |
30 | 31 | ||
31 | #include "dispc.h" | 32 | #include "dispc.h" |
32 | 33 | ||
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 1e642b7a20fe..f24df0b54e1c 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c | |||
@@ -26,9 +26,9 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | 28 | ||
29 | #include <asm/arch/dma.h> | 29 | #include <mach/dma.h> |
30 | #include <asm/arch/omapfb.h> | 30 | #include <mach/omapfb.h> |
31 | #include <asm/arch/hwa742.h> | 31 | #include <mach/hwa742.h> |
32 | 32 | ||
33 | #define HWA742_REV_CODE_REG 0x0 | 33 | #define HWA742_REV_CODE_REG 0x0 |
34 | #define HWA742_CONFIG_REG 0x2 | 34 | #define HWA742_CONFIG_REG 0x2 |
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c index 31e978349a80..2486237ebba5 100644 --- a/drivers/video/omap/lcd_h3.c +++ b/drivers/video/omap/lcd_h3.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/i2c/tps65010.h> | 24 | #include <linux/i2c/tps65010.h> |
25 | 25 | ||
26 | #include <asm/arch/gpio.h> | 26 | #include <mach/gpio.h> |
27 | #include <asm/arch/omapfb.h> | 27 | #include <mach/omapfb.h> |
28 | 28 | ||
29 | #define MODULE_NAME "omapfb-lcd_h3" | 29 | #define MODULE_NAME "omapfb-lcd_h3" |
30 | 30 | ||
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c index fd6f0eb16de1..88c19d424ef7 100644 --- a/drivers/video/omap/lcd_h4.c +++ b/drivers/video/omap/lcd_h4.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | 24 | ||
25 | #include <asm/arch/omapfb.h> | 25 | #include <mach/omapfb.h> |
26 | 26 | ||
27 | static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | 27 | static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) |
28 | { | 28 | { |
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c index 551f385861d1..6953ed4b5820 100644 --- a/drivers/video/omap/lcd_inn1510.c +++ b/drivers/video/omap/lcd_inn1510.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | ||
26 | #include <asm/arch/fpga.h> | 26 | #include <mach/fpga.h> |
27 | #include <asm/arch/omapfb.h> | 27 | #include <mach/omapfb.h> |
28 | 28 | ||
29 | static int innovator1510_panel_init(struct lcd_panel *panel, | 29 | static int innovator1510_panel_init(struct lcd_panel *panel, |
30 | struct omapfb_device *fbdev) | 30 | struct omapfb_device *fbdev) |
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c index 5ef119c813e0..6a42c6a0cd99 100644 --- a/drivers/video/omap/lcd_inn1610.c +++ b/drivers/video/omap/lcd_inn1610.c | |||
@@ -22,8 +22,8 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | 24 | ||
25 | #include <asm/arch/gpio.h> | 25 | #include <mach/gpio.h> |
26 | #include <asm/arch/omapfb.h> | 26 | #include <mach/omapfb.h> |
27 | 27 | ||
28 | #define MODULE_NAME "omapfb-lcd_h3" | 28 | #define MODULE_NAME "omapfb-lcd_h3" |
29 | 29 | ||
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c index a38038840fd6..a4a725f427a4 100644 --- a/drivers/video/omap/lcd_osk.c +++ b/drivers/video/omap/lcd_osk.c | |||
@@ -23,9 +23,9 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/arch/gpio.h> | 26 | #include <mach/gpio.h> |
27 | #include <asm/arch/mux.h> | 27 | #include <mach/mux.h> |
28 | #include <asm/arch/omapfb.h> | 28 | #include <mach/omapfb.h> |
29 | 29 | ||
30 | static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | 30 | static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) |
31 | { | 31 | { |
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c index 52bdfdac42c9..218317366e6e 100644 --- a/drivers/video/omap/lcd_palmte.c +++ b/drivers/video/omap/lcd_palmte.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | ||
26 | #include <asm/arch/fpga.h> | 26 | #include <mach/fpga.h> |
27 | #include <asm/arch/omapfb.h> | 27 | #include <mach/omapfb.h> |
28 | 28 | ||
29 | static int palmte_panel_init(struct lcd_panel *panel, | 29 | static int palmte_panel_init(struct lcd_panel *panel, |
30 | struct omapfb_device *fbdev) | 30 | struct omapfb_device *fbdev) |
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c index 4bb349f54356..57b0f6cf6a5a 100644 --- a/drivers/video/omap/lcd_palmtt.c +++ b/drivers/video/omap/lcd_palmtt.c | |||
@@ -29,8 +29,8 @@ GPIO13 - screen blanking | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | 31 | ||
32 | #include <asm/arch/gpio.h> | 32 | #include <mach/gpio.h> |
33 | #include <asm/arch/omapfb.h> | 33 | #include <mach/omapfb.h> |
34 | 34 | ||
35 | static int palmtt_panel_init(struct lcd_panel *panel, | 35 | static int palmtt_panel_init(struct lcd_panel *panel, |
36 | struct omapfb_device *fbdev) | 36 | struct omapfb_device *fbdev) |
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c index ea6170ddff35..d33d78b11723 100644 --- a/drivers/video/omap/lcd_palmz71.c +++ b/drivers/video/omap/lcd_palmz71.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | 26 | ||
27 | #include <asm/arch/omapfb.h> | 27 | #include <mach/omapfb.h> |
28 | 28 | ||
29 | static int palmz71_panel_init(struct lcd_panel *panel, | 29 | static int palmz71_panel_init(struct lcd_panel *panel, |
30 | struct omapfb_device *fbdev) | 30 | struct omapfb_device *fbdev) |
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c index c4f306a4e5c9..caa6a896cb8b 100644 --- a/drivers/video/omap/lcd_sx1.c +++ b/drivers/video/omap/lcd_sx1.c | |||
@@ -23,10 +23,10 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | ||
26 | #include <asm/arch/gpio.h> | 26 | #include <mach/gpio.h> |
27 | #include <asm/arch/omapfb.h> | 27 | #include <mach/omapfb.h> |
28 | #include <asm/arch/mcbsp.h> | 28 | #include <mach/mcbsp.h> |
29 | #include <asm/arch/mux.h> | 29 | #include <mach/mux.h> |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * OMAP310 GPIO registers | 32 | * OMAP310 GPIO registers |
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index fb19ed4992db..83514f066712 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c | |||
@@ -29,8 +29,8 @@ | |||
29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | 31 | ||
32 | #include <asm/arch/dma.h> | 32 | #include <mach/dma.h> |
33 | #include <asm/arch/omapfb.h> | 33 | #include <mach/omapfb.h> |
34 | 34 | ||
35 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
36 | 36 | ||
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 14d0f7a11145..51a138bd113c 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -25,11 +25,11 @@ | |||
25 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 25 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
26 | */ | 26 | */ |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/mm.h> | ||
28 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
29 | 30 | ||
30 | #include <asm/mach-types.h> | 31 | #include <mach/dma.h> |
31 | #include <asm/arch/dma.h> | 32 | #include <mach/omapfb.h> |
32 | #include <asm/arch/omapfb.h> | ||
33 | 33 | ||
34 | #define MODULE_NAME "omapfb" | 34 | #define MODULE_NAME "omapfb" |
35 | 35 | ||
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index 789cfd23c36b..4a6f13d3facf 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | 29 | ||
30 | #include <asm/arch/omapfb.h> | 30 | #include <mach/omapfb.h> |
31 | 31 | ||
32 | #include "dispc.h" | 32 | #include "dispc.h" |
33 | 33 | ||
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c index 81dbcf53cf0e..6359353c2c67 100644 --- a/drivers/video/omap/sossi.c +++ b/drivers/video/omap/sossi.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | 26 | ||
27 | #include <asm/arch/dma.h> | 27 | #include <mach/dma.h> |
28 | #include <asm/arch/omapfb.h> | 28 | #include <mach/omapfb.h> |
29 | 29 | ||
30 | #include "lcdc.h" | 30 | #include "lcdc.h" |
31 | 31 | ||
@@ -646,7 +646,7 @@ static int sossi_init(struct omapfb_device *fbdev) | |||
646 | sossi_write_reg(SOSSI_INIT1_REG, l); | 646 | sossi_write_reg(SOSSI_INIT1_REG, l); |
647 | 647 | ||
648 | if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq, | 648 | if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq, |
649 | IRQT_FALLING, | 649 | IRQ_TYPE_EDGE_FALLING, |
650 | "sossi_match", sossi.fbdev->dev)) < 0) { | 650 | "sossi_match", sossi.fbdev->dev)) < 0) { |
651 | dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n"); | 651 | dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n"); |
652 | goto err; | 652 | goto err; |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 3f1ca2adda3d..c6dd924976a4 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -1746,6 +1746,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev) | |||
1746 | release_mem_region(fix->mmio_start, fix->mmio_len); | 1746 | release_mem_region(fix->mmio_start, fix->mmio_len); |
1747 | 1747 | ||
1748 | pci_set_drvdata(pdev, NULL); | 1748 | pci_set_drvdata(pdev, NULL); |
1749 | fb_dealloc_cmap(&info->cmap); | ||
1749 | kfree(info->pixmap.addr); | 1750 | kfree(info->pixmap.addr); |
1750 | kfree(info); | 1751 | kfree(info); |
1751 | } | 1752 | } |
diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h index d80a614d89ed..1234d4375d92 100644 --- a/drivers/video/pnx4008/dum.h +++ b/drivers/video/pnx4008/dum.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #ifndef __PNX008_DUM_H__ | 12 | #ifndef __PNX008_DUM_H__ |
13 | #define __PNX008_DUM_H__ | 13 | #define __PNX008_DUM_H__ |
14 | 14 | ||
15 | #include <asm/arch/platform.h> | 15 | #include <mach/platform.h> |
16 | 16 | ||
17 | #define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE) | 17 | #define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE) |
18 | #define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE) | 18 | #define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE) |
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c index d23bf0d659b6..2aa09bce3944 100644 --- a/drivers/video/pnx4008/sdum.c +++ b/drivers/video/pnx4008/sdum.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> |
31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <asm/arch/gpio.h> | 33 | #include <mach/gpio.h> |
34 | 34 | ||
35 | #include "sdum.h" | 35 | #include "sdum.h" |
36 | #include "fbcommon.h" | 36 | #include "fbcommon.h" |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index dc3af1c78c56..4b5d80771904 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -1297,6 +1297,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | |||
1297 | 1297 | ||
1298 | static struct ps3_system_bus_driver ps3fb_driver = { | 1298 | static struct ps3_system_bus_driver ps3fb_driver = { |
1299 | .match_id = PS3_MATCH_ID_GRAPHICS, | 1299 | .match_id = PS3_MATCH_ID_GRAPHICS, |
1300 | .match_sub_id = PS3_MATCH_SUB_ID_FB, | ||
1300 | .core.name = DEVICE_NAME, | 1301 | .core.name = DEVICE_NAME, |
1301 | .core.owner = THIS_MODULE, | 1302 | .core.owner = THIS_MODULE, |
1302 | .probe = ps3fb_probe, | 1303 | .probe = ps3fb_probe, |
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 8c863a7f654b..0a0fd48a8566 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c | |||
@@ -58,18 +58,18 @@ | |||
58 | 58 | ||
59 | #ifdef CONFIG_SH_DREAMCAST | 59 | #ifdef CONFIG_SH_DREAMCAST |
60 | #include <asm/machvec.h> | 60 | #include <asm/machvec.h> |
61 | #include <asm/mach/sysasic.h> | 61 | #include <mach-dreamcast/mach/sysasic.h> |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #ifdef CONFIG_SH_DMA | 64 | #ifdef CONFIG_SH_DMA |
65 | #include <linux/pagemap.h> | 65 | #include <linux/pagemap.h> |
66 | #include <asm/mach/dma.h> | 66 | #include <mach/dma.h> |
67 | #include <asm/dma.h> | 67 | #include <asm/dma.h> |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #ifdef CONFIG_SH_STORE_QUEUES | 70 | #ifdef CONFIG_SH_STORE_QUEUES |
71 | #include <linux/uaccess.h> | 71 | #include <linux/uaccess.h> |
72 | #include <asm/cpu/sq.h> | 72 | #include <cpu/sq.h> |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | #ifndef PCI_DEVICE_ID_NEC_NEON250 | 75 | #ifndef PCI_DEVICE_ID_NEC_NEON250 |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index d0746261c957..97204497d9f7 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/string.h> | 30 | #include <linux/string.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/mm.h> | ||
33 | #include <linux/fb.h> | 34 | #include <linux/fb.h> |
34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
35 | #include <linux/init.h> | 36 | #include <linux/init.h> |
@@ -40,17 +41,18 @@ | |||
40 | #include <linux/clk.h> | 41 | #include <linux/clk.h> |
41 | #include <linux/err.h> | 42 | #include <linux/err.h> |
42 | #include <linux/completion.h> | 43 | #include <linux/completion.h> |
44 | #include <linux/mutex.h> | ||
43 | #include <linux/kthread.h> | 45 | #include <linux/kthread.h> |
44 | #include <linux/freezer.h> | 46 | #include <linux/freezer.h> |
45 | 47 | ||
46 | #include <asm/hardware.h> | 48 | #include <mach/hardware.h> |
47 | #include <asm/io.h> | 49 | #include <asm/io.h> |
48 | #include <asm/irq.h> | 50 | #include <asm/irq.h> |
49 | #include <asm/div64.h> | 51 | #include <asm/div64.h> |
50 | #include <asm/arch/pxa-regs.h> | 52 | #include <mach/pxa-regs.h> |
51 | #include <asm/arch/pxa2xx-gpio.h> | 53 | #include <mach/pxa2xx-gpio.h> |
52 | #include <asm/arch/bitfield.h> | 54 | #include <mach/bitfield.h> |
53 | #include <asm/arch/pxafb.h> | 55 | #include <mach/pxafb.h> |
54 | 56 | ||
55 | /* | 57 | /* |
56 | * Complain if VAR is out of range. | 58 | * Complain if VAR is out of range. |
@@ -227,6 +229,22 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var) | |||
227 | case 4: ret = LCCR3_4BPP; break; | 229 | case 4: ret = LCCR3_4BPP; break; |
228 | case 8: ret = LCCR3_8BPP; break; | 230 | case 8: ret = LCCR3_8BPP; break; |
229 | case 16: ret = LCCR3_16BPP; break; | 231 | case 16: ret = LCCR3_16BPP; break; |
232 | case 24: | ||
233 | switch (var->red.length + var->green.length + | ||
234 | var->blue.length + var->transp.length) { | ||
235 | case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break; | ||
236 | case 19: ret = LCCR3_19BPP_P; break; | ||
237 | } | ||
238 | break; | ||
239 | case 32: | ||
240 | switch (var->red.length + var->green.length + | ||
241 | var->blue.length + var->transp.length) { | ||
242 | case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break; | ||
243 | case 19: ret = LCCR3_19BPP; break; | ||
244 | case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break; | ||
245 | case 25: ret = LCCR3_25BPP; break; | ||
246 | } | ||
247 | break; | ||
230 | } | 248 | } |
231 | return ret; | 249 | return ret; |
232 | } | 250 | } |
@@ -345,6 +363,41 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
345 | var->green.offset = 5; var->green.length = 6; | 363 | var->green.offset = 5; var->green.length = 6; |
346 | var->blue.offset = 0; var->blue.length = 5; | 364 | var->blue.offset = 0; var->blue.length = 5; |
347 | var->transp.offset = var->transp.length = 0; | 365 | var->transp.offset = var->transp.length = 0; |
366 | } else if (var->bits_per_pixel > 16) { | ||
367 | struct pxafb_mode_info *mode; | ||
368 | |||
369 | mode = pxafb_getmode(inf, var); | ||
370 | if (!mode) | ||
371 | return -EINVAL; | ||
372 | |||
373 | switch (mode->depth) { | ||
374 | case 18: /* RGB666 */ | ||
375 | var->transp.offset = var->transp.length = 0; | ||
376 | var->red.offset = 12; var->red.length = 6; | ||
377 | var->green.offset = 6; var->green.length = 6; | ||
378 | var->blue.offset = 0; var->blue.length = 6; | ||
379 | break; | ||
380 | case 19: /* RGBT666 */ | ||
381 | var->transp.offset = 18; var->transp.length = 1; | ||
382 | var->red.offset = 12; var->red.length = 6; | ||
383 | var->green.offset = 6; var->green.length = 6; | ||
384 | var->blue.offset = 0; var->blue.length = 6; | ||
385 | break; | ||
386 | case 24: /* RGB888 */ | ||
387 | var->transp.offset = var->transp.length = 0; | ||
388 | var->red.offset = 16; var->red.length = 8; | ||
389 | var->green.offset = 8; var->green.length = 8; | ||
390 | var->blue.offset = 0; var->blue.length = 8; | ||
391 | break; | ||
392 | case 25: /* RGBT888 */ | ||
393 | var->transp.offset = 24; var->transp.length = 1; | ||
394 | var->red.offset = 16; var->red.length = 8; | ||
395 | var->green.offset = 8; var->green.length = 8; | ||
396 | var->blue.offset = 0; var->blue.length = 8; | ||
397 | break; | ||
398 | default: | ||
399 | return -EINVAL; | ||
400 | } | ||
348 | } else { | 401 | } else { |
349 | var->red.offset = var->green.offset = 0; | 402 | var->red.offset = var->green.offset = 0; |
350 | var->blue.offset = var->transp.offset = 0; | 403 | var->blue.offset = var->transp.offset = 0; |
@@ -376,7 +429,7 @@ static int pxafb_set_par(struct fb_info *info) | |||
376 | struct pxafb_info *fbi = (struct pxafb_info *)info; | 429 | struct pxafb_info *fbi = (struct pxafb_info *)info; |
377 | struct fb_var_screeninfo *var = &info->var; | 430 | struct fb_var_screeninfo *var = &info->var; |
378 | 431 | ||
379 | if (var->bits_per_pixel == 16) | 432 | if (var->bits_per_pixel >= 16) |
380 | fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; | 433 | fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; |
381 | else if (!fbi->cmap_static) | 434 | else if (!fbi->cmap_static) |
382 | fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; | 435 | fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; |
@@ -391,7 +444,7 @@ static int pxafb_set_par(struct fb_info *info) | |||
391 | 444 | ||
392 | fbi->fb.fix.line_length = var->xres_virtual * | 445 | fbi->fb.fix.line_length = var->xres_virtual * |
393 | var->bits_per_pixel / 8; | 446 | var->bits_per_pixel / 8; |
394 | if (var->bits_per_pixel == 16) | 447 | if (var->bits_per_pixel >= 16) |
395 | fbi->palette_size = 0; | 448 | fbi->palette_size = 0; |
396 | else | 449 | else |
397 | fbi->palette_size = var->bits_per_pixel == 1 ? | 450 | fbi->palette_size = var->bits_per_pixel == 1 ? |
@@ -404,7 +457,7 @@ static int pxafb_set_par(struct fb_info *info) | |||
404 | */ | 457 | */ |
405 | pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); | 458 | pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); |
406 | 459 | ||
407 | if (fbi->fb.var.bits_per_pixel == 16) | 460 | if (fbi->fb.var.bits_per_pixel >= 16) |
408 | fb_dealloc_cmap(&fbi->fb.cmap); | 461 | fb_dealloc_cmap(&fbi->fb.cmap); |
409 | else | 462 | else |
410 | fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0); | 463 | fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0); |
@@ -831,6 +884,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, | |||
831 | case 4: | 884 | case 4: |
832 | case 8: | 885 | case 8: |
833 | case 16: | 886 | case 16: |
887 | case 24: | ||
888 | case 32: | ||
834 | break; | 889 | break; |
835 | default: | 890 | default: |
836 | printk(KERN_ERR "%s: invalid bit depth %d\n", | 891 | printk(KERN_ERR "%s: invalid bit depth %d\n", |
@@ -968,10 +1023,17 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi) | |||
968 | 1023 | ||
969 | for (gpio = 58; ldd_bits; gpio++, ldd_bits--) | 1024 | for (gpio = 58; ldd_bits; gpio++, ldd_bits--) |
970 | pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT); | 1025 | pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT); |
1026 | /* 18 bit interface */ | ||
1027 | if (fbi->fb.var.bits_per_pixel > 16) { | ||
1028 | pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT); | ||
1029 | pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT); | ||
1030 | } | ||
971 | pxa_gpio_mode(GPIO74_LCD_FCLK_MD); | 1031 | pxa_gpio_mode(GPIO74_LCD_FCLK_MD); |
972 | pxa_gpio_mode(GPIO75_LCD_LCLK_MD); | 1032 | pxa_gpio_mode(GPIO75_LCD_LCLK_MD); |
973 | pxa_gpio_mode(GPIO76_LCD_PCLK_MD); | 1033 | pxa_gpio_mode(GPIO76_LCD_PCLK_MD); |
974 | pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); | 1034 | |
1035 | if ((lccr0 & LCCR0_PAS) == 0) | ||
1036 | pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); | ||
975 | } | 1037 | } |
976 | 1038 | ||
977 | static void pxafb_enable_controller(struct pxafb_info *fbi) | 1039 | static void pxafb_enable_controller(struct pxafb_info *fbi) |
@@ -1058,7 +1120,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) | |||
1058 | { | 1120 | { |
1059 | u_int old_state; | 1121 | u_int old_state; |
1060 | 1122 | ||
1061 | down(&fbi->ctrlr_sem); | 1123 | mutex_lock(&fbi->ctrlr_lock); |
1062 | 1124 | ||
1063 | old_state = fbi->state; | 1125 | old_state = fbi->state; |
1064 | 1126 | ||
@@ -1146,7 +1208,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) | |||
1146 | } | 1208 | } |
1147 | break; | 1209 | break; |
1148 | } | 1210 | } |
1149 | up(&fbi->ctrlr_sem); | 1211 | mutex_unlock(&fbi->ctrlr_lock); |
1150 | } | 1212 | } |
1151 | 1213 | ||
1152 | /* | 1214 | /* |
@@ -1276,7 +1338,7 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi) | |||
1276 | fbi->dma_buff_phys = fbi->map_dma; | 1338 | fbi->dma_buff_phys = fbi->map_dma; |
1277 | fbi->palette_cpu = (u16 *) fbi->dma_buff->palette; | 1339 | fbi->palette_cpu = (u16 *) fbi->dma_buff->palette; |
1278 | 1340 | ||
1279 | pr_debug("pxafb: palette_mem_size = 0x%08lx\n", fbi->palette_size*sizeof(u16)); | 1341 | pr_debug("pxafb: palette_mem_size = 0x%08x\n", fbi->palette_size*sizeof(u16)); |
1280 | 1342 | ||
1281 | #ifdef CONFIG_FB_PXA_SMARTPANEL | 1343 | #ifdef CONFIG_FB_PXA_SMARTPANEL |
1282 | fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; | 1344 | fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; |
@@ -1340,6 +1402,8 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi, | |||
1340 | if (lcd_conn == LCD_MONO_STN_8BPP) | 1402 | if (lcd_conn == LCD_MONO_STN_8BPP) |
1341 | fbi->lccr0 |= LCCR0_DPD; | 1403 | fbi->lccr0 |= LCCR0_DPD; |
1342 | 1404 | ||
1405 | fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0; | ||
1406 | |||
1343 | fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff); | 1407 | fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff); |
1344 | fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0; | 1408 | fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0; |
1345 | fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; | 1409 | fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; |
@@ -1399,7 +1463,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) | |||
1399 | 1463 | ||
1400 | init_waitqueue_head(&fbi->ctrlr_wait); | 1464 | init_waitqueue_head(&fbi->ctrlr_wait); |
1401 | INIT_WORK(&fbi->task, pxafb_task); | 1465 | INIT_WORK(&fbi->task, pxafb_task); |
1402 | init_MUTEX(&fbi->ctrlr_sem); | 1466 | mutex_init(&fbi->ctrlr_lock); |
1403 | init_completion(&fbi->disable_done); | 1467 | init_completion(&fbi->disable_done); |
1404 | #ifdef CONFIG_FB_PXA_SMARTPANEL | 1468 | #ifdef CONFIG_FB_PXA_SMARTPANEL |
1405 | init_completion(&fbi->command_done); | 1469 | init_completion(&fbi->command_done); |
@@ -1613,53 +1677,63 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)"); | |||
1613 | #define pxafb_setup_options() (0) | 1677 | #define pxafb_setup_options() (0) |
1614 | #endif | 1678 | #endif |
1615 | 1679 | ||
1616 | static int __devinit pxafb_probe(struct platform_device *dev) | ||
1617 | { | ||
1618 | struct pxafb_info *fbi; | ||
1619 | struct pxafb_mach_info *inf; | ||
1620 | struct resource *r; | ||
1621 | int irq, ret; | ||
1622 | |||
1623 | dev_dbg(&dev->dev, "pxafb_probe\n"); | ||
1624 | |||
1625 | inf = dev->dev.platform_data; | ||
1626 | ret = -ENOMEM; | ||
1627 | fbi = NULL; | ||
1628 | if (!inf) | ||
1629 | goto failed; | ||
1630 | |||
1631 | ret = pxafb_parse_options(&dev->dev, g_options); | ||
1632 | if (ret < 0) | ||
1633 | goto failed; | ||
1634 | |||
1635 | #ifdef DEBUG_VAR | 1680 | #ifdef DEBUG_VAR |
1636 | /* Check for various illegal bit-combinations. Currently only | 1681 | /* Check for various illegal bit-combinations. Currently only |
1637 | * a warning is given. */ | 1682 | * a warning is given. */ |
1683 | static void __devinit pxafb_check_options(struct device *dev, | ||
1684 | struct pxafb_mach_info *inf) | ||
1685 | { | ||
1686 | if (inf->lcd_conn) | ||
1687 | return; | ||
1638 | 1688 | ||
1639 | if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) | 1689 | if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) |
1640 | dev_warn(&dev->dev, "machine LCCR0 setting contains " | 1690 | dev_warn(dev, "machine LCCR0 setting contains " |
1641 | "illegal bits: %08x\n", | 1691 | "illegal bits: %08x\n", |
1642 | inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); | 1692 | inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); |
1643 | if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) | 1693 | if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) |
1644 | dev_warn(&dev->dev, "machine LCCR3 setting contains " | 1694 | dev_warn(dev, "machine LCCR3 setting contains " |
1645 | "illegal bits: %08x\n", | 1695 | "illegal bits: %08x\n", |
1646 | inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); | 1696 | inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); |
1647 | if (inf->lccr0 & LCCR0_DPD && | 1697 | if (inf->lccr0 & LCCR0_DPD && |
1648 | ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || | 1698 | ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || |
1649 | (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || | 1699 | (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || |
1650 | (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) | 1700 | (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) |
1651 | dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is " | 1701 | dev_warn(dev, "Double Pixel Data (DPD) mode is " |
1652 | "only valid in passive mono" | 1702 | "only valid in passive mono" |
1653 | " single panel mode\n"); | 1703 | " single panel mode\n"); |
1654 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && | 1704 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && |
1655 | (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) | 1705 | (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) |
1656 | dev_warn(&dev->dev, "Dual panel only valid in passive mode\n"); | 1706 | dev_warn(dev, "Dual panel only valid in passive mode\n"); |
1657 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && | 1707 | if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && |
1658 | (inf->modes->upper_margin || inf->modes->lower_margin)) | 1708 | (inf->modes->upper_margin || inf->modes->lower_margin)) |
1659 | dev_warn(&dev->dev, "Upper and lower margins must be 0 in " | 1709 | dev_warn(dev, "Upper and lower margins must be 0 in " |
1660 | "passive mode\n"); | 1710 | "passive mode\n"); |
1711 | } | ||
1712 | #else | ||
1713 | #define pxafb_check_options(...) do {} while (0) | ||
1661 | #endif | 1714 | #endif |
1662 | 1715 | ||
1716 | static int __devinit pxafb_probe(struct platform_device *dev) | ||
1717 | { | ||
1718 | struct pxafb_info *fbi; | ||
1719 | struct pxafb_mach_info *inf; | ||
1720 | struct resource *r; | ||
1721 | int irq, ret; | ||
1722 | |||
1723 | dev_dbg(&dev->dev, "pxafb_probe\n"); | ||
1724 | |||
1725 | inf = dev->dev.platform_data; | ||
1726 | ret = -ENOMEM; | ||
1727 | fbi = NULL; | ||
1728 | if (!inf) | ||
1729 | goto failed; | ||
1730 | |||
1731 | ret = pxafb_parse_options(&dev->dev, g_options); | ||
1732 | if (ret < 0) | ||
1733 | goto failed; | ||
1734 | |||
1735 | pxafb_check_options(&dev->dev, inf); | ||
1736 | |||
1663 | dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n", | 1737 | dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n", |
1664 | inf->modes->xres, | 1738 | inf->modes->xres, |
1665 | inf->modes->yres, | 1739 | inf->modes->yres, |
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 8238dc826429..31541b86f13d 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h | |||
@@ -106,7 +106,7 @@ struct pxafb_info { | |||
106 | 106 | ||
107 | volatile u_char state; | 107 | volatile u_char state; |
108 | volatile u_char task_state; | 108 | volatile u_char task_state; |
109 | struct semaphore ctrlr_sem; | 109 | struct mutex ctrlr_lock; |
110 | wait_queue_head_t ctrlr_wait; | 110 | wait_queue_head_t ctrlr_wait; |
111 | struct work_struct task; | 111 | struct work_struct task; |
112 | 112 | ||
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index f0598961c6b0..79cf0b1976aa 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -29,9 +29,9 @@ | |||
29 | #include <asm/div64.h> | 29 | #include <asm/div64.h> |
30 | 30 | ||
31 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
32 | #include <asm/arch/regs-lcd.h> | 32 | #include <mach/regs-lcd.h> |
33 | #include <asm/arch/regs-gpio.h> | 33 | #include <mach/regs-gpio.h> |
34 | #include <asm/arch/fb.h> | 34 | #include <mach/fb.h> |
35 | 35 | ||
36 | #ifdef CONFIG_PM | 36 | #ifdef CONFIG_PM |
37 | #include <linux/pm.h> | 37 | #include <linux/pm.h> |
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 2972f112dbed..4dcec48a1d78 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * which is based on the code of neofb. | 11 | * which is based on the code of neofb. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/version.h> | ||
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
@@ -903,13 +902,13 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
903 | /* Prepare PCI device */ | 902 | /* Prepare PCI device */ |
904 | rc = pci_enable_device(dev); | 903 | rc = pci_enable_device(dev); |
905 | if (rc < 0) { | 904 | if (rc < 0) { |
906 | dev_err(info->dev, "cannot enable PCI device\n"); | 905 | dev_err(info->device, "cannot enable PCI device\n"); |
907 | goto err_enable_device; | 906 | goto err_enable_device; |
908 | } | 907 | } |
909 | 908 | ||
910 | rc = pci_request_regions(dev, "s3fb"); | 909 | rc = pci_request_regions(dev, "s3fb"); |
911 | if (rc < 0) { | 910 | if (rc < 0) { |
912 | dev_err(info->dev, "cannot reserve framebuffer region\n"); | 911 | dev_err(info->device, "cannot reserve framebuffer region\n"); |
913 | goto err_request_regions; | 912 | goto err_request_regions; |
914 | } | 913 | } |
915 | 914 | ||
@@ -921,7 +920,7 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
921 | info->screen_base = pci_iomap(dev, 0, 0); | 920 | info->screen_base = pci_iomap(dev, 0, 0); |
922 | if (! info->screen_base) { | 921 | if (! info->screen_base) { |
923 | rc = -ENOMEM; | 922 | rc = -ENOMEM; |
924 | dev_err(info->dev, "iomap for framebuffer failed\n"); | 923 | dev_err(info->device, "iomap for framebuffer failed\n"); |
925 | goto err_iomap; | 924 | goto err_iomap; |
926 | } | 925 | } |
927 | 926 | ||
@@ -965,19 +964,19 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
965 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 964 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); |
966 | if (! ((rc == 1) || (rc == 2))) { | 965 | if (! ((rc == 1) || (rc == 2))) { |
967 | rc = -EINVAL; | 966 | rc = -EINVAL; |
968 | dev_err(info->dev, "mode %s not found\n", mode_option); | 967 | dev_err(info->device, "mode %s not found\n", mode_option); |
969 | goto err_find_mode; | 968 | goto err_find_mode; |
970 | } | 969 | } |
971 | 970 | ||
972 | rc = fb_alloc_cmap(&info->cmap, 256, 0); | 971 | rc = fb_alloc_cmap(&info->cmap, 256, 0); |
973 | if (rc < 0) { | 972 | if (rc < 0) { |
974 | dev_err(info->dev, "cannot allocate colormap\n"); | 973 | dev_err(info->device, "cannot allocate colormap\n"); |
975 | goto err_alloc_cmap; | 974 | goto err_alloc_cmap; |
976 | } | 975 | } |
977 | 976 | ||
978 | rc = register_framebuffer(info); | 977 | rc = register_framebuffer(info); |
979 | if (rc < 0) { | 978 | if (rc < 0) { |
980 | dev_err(info->dev, "cannot register framebuffer\n"); | 979 | dev_err(info->device, "cannot register framebuffer\n"); |
981 | goto err_reg_fb; | 980 | goto err_reg_fb; |
982 | } | 981 | } |
983 | 982 | ||
@@ -1053,7 +1052,7 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) | |||
1053 | struct fb_info *info = pci_get_drvdata(dev); | 1052 | struct fb_info *info = pci_get_drvdata(dev); |
1054 | struct s3fb_info *par = info->par; | 1053 | struct s3fb_info *par = info->par; |
1055 | 1054 | ||
1056 | dev_info(info->dev, "suspend\n"); | 1055 | dev_info(info->device, "suspend\n"); |
1057 | 1056 | ||
1058 | acquire_console_sem(); | 1057 | acquire_console_sem(); |
1059 | mutex_lock(&(par->open_lock)); | 1058 | mutex_lock(&(par->open_lock)); |
@@ -1085,7 +1084,7 @@ static int s3_pci_resume(struct pci_dev* dev) | |||
1085 | struct s3fb_info *par = info->par; | 1084 | struct s3fb_info *par = info->par; |
1086 | int err; | 1085 | int err; |
1087 | 1086 | ||
1088 | dev_info(info->dev, "resume\n"); | 1087 | dev_info(info->device, "resume\n"); |
1089 | 1088 | ||
1090 | acquire_console_sem(); | 1089 | acquire_console_sem(); |
1091 | mutex_lock(&(par->open_lock)); | 1090 | mutex_lock(&(par->open_lock)); |
@@ -1102,7 +1101,7 @@ static int s3_pci_resume(struct pci_dev* dev) | |||
1102 | if (err) { | 1101 | if (err) { |
1103 | mutex_unlock(&(par->open_lock)); | 1102 | mutex_unlock(&(par->open_lock)); |
1104 | release_console_sem(); | 1103 | release_console_sem(); |
1105 | dev_err(info->dev, "error %d enabling device for resume\n", err); | 1104 | dev_err(info->device, "error %d enabling device for resume\n", err); |
1106 | return err; | 1105 | return err; |
1107 | } | 1106 | } |
1108 | pci_set_master(dev); | 1107 | pci_set_master(dev); |
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index ab2b2110478b..c052bd4c0b06 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c | |||
@@ -167,6 +167,7 @@ | |||
167 | #include <linux/string.h> | 167 | #include <linux/string.h> |
168 | #include <linux/interrupt.h> | 168 | #include <linux/interrupt.h> |
169 | #include <linux/slab.h> | 169 | #include <linux/slab.h> |
170 | #include <linux/mm.h> | ||
170 | #include <linux/fb.h> | 171 | #include <linux/fb.h> |
171 | #include <linux/delay.h> | 172 | #include <linux/delay.h> |
172 | #include <linux/init.h> | 173 | #include <linux/init.h> |
@@ -174,12 +175,13 @@ | |||
174 | #include <linux/cpufreq.h> | 175 | #include <linux/cpufreq.h> |
175 | #include <linux/platform_device.h> | 176 | #include <linux/platform_device.h> |
176 | #include <linux/dma-mapping.h> | 177 | #include <linux/dma-mapping.h> |
178 | #include <linux/mutex.h> | ||
177 | 179 | ||
178 | #include <asm/hardware.h> | 180 | #include <mach/hardware.h> |
179 | #include <asm/io.h> | 181 | #include <asm/io.h> |
180 | #include <asm/mach-types.h> | 182 | #include <asm/mach-types.h> |
181 | #include <asm/arch/assabet.h> | 183 | #include <mach/assabet.h> |
182 | #include <asm/arch/shannon.h> | 184 | #include <mach/shannon.h> |
183 | 185 | ||
184 | /* | 186 | /* |
185 | * debugging? | 187 | * debugging? |
@@ -1107,7 +1109,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) | |||
1107 | { | 1109 | { |
1108 | u_int old_state; | 1110 | u_int old_state; |
1109 | 1111 | ||
1110 | down(&fbi->ctrlr_sem); | 1112 | mutex_lock(&fbi->ctrlr_lock); |
1111 | 1113 | ||
1112 | old_state = fbi->state; | 1114 | old_state = fbi->state; |
1113 | 1115 | ||
@@ -1192,7 +1194,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) | |||
1192 | } | 1194 | } |
1193 | break; | 1195 | break; |
1194 | } | 1196 | } |
1195 | up(&fbi->ctrlr_sem); | 1197 | mutex_unlock(&fbi->ctrlr_lock); |
1196 | } | 1198 | } |
1197 | 1199 | ||
1198 | /* | 1200 | /* |
@@ -1444,7 +1446,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) | |||
1444 | 1446 | ||
1445 | init_waitqueue_head(&fbi->ctrlr_wait); | 1447 | init_waitqueue_head(&fbi->ctrlr_wait); |
1446 | INIT_WORK(&fbi->task, sa1100fb_task); | 1448 | INIT_WORK(&fbi->task, sa1100fb_task); |
1447 | init_MUTEX(&fbi->ctrlr_sem); | 1449 | mutex_init(&fbi->ctrlr_lock); |
1448 | 1450 | ||
1449 | return fbi; | 1451 | return fbi; |
1450 | } | 1452 | } |
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h index f465b27ed860..86831db9a042 100644 --- a/drivers/video/sa1100fb.h +++ b/drivers/video/sa1100fb.h | |||
@@ -100,7 +100,7 @@ struct sa1100fb_info { | |||
100 | 100 | ||
101 | volatile u_char state; | 101 | volatile u_char state; |
102 | volatile u_char task_state; | 102 | volatile u_char task_state; |
103 | struct semaphore ctrlr_sem; | 103 | struct mutex ctrlr_lock; |
104 | wait_queue_head_t ctrlr_wait; | 104 | wait_queue_head_t ctrlr_wait; |
105 | struct work_struct task; | 105 | struct work_struct task; |
106 | 106 | ||
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c new file mode 100644 index 000000000000..8d0212da4514 --- /dev/null +++ b/drivers/video/sh7760fb.c | |||
@@ -0,0 +1,659 @@ | |||
1 | /* | ||
2 | * SH7760/SH7763 LCDC Framebuffer driver. | ||
3 | * | ||
4 | * (c) 2006-2008 MSC Vertriebsges.m.b.H., | ||
5 | * Manuel Lauss <mano@roarinelk.homelinux.net> | ||
6 | * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com> | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General | ||
9 | * Public License. See the file COPYING in the main directory of this | ||
10 | * archive for more details. | ||
11 | * | ||
12 | * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt! | ||
13 | * | ||
14 | * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de> | ||
15 | * for his original source and testing! | ||
16 | */ | ||
17 | |||
18 | #include <linux/completion.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/dma-mapping.h> | ||
21 | #include <linux/fb.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #include <asm/sh7760fb.h> | ||
29 | |||
30 | struct sh7760fb_par { | ||
31 | void __iomem *base; | ||
32 | int irq; | ||
33 | |||
34 | struct sh7760fb_platdata *pd; /* display information */ | ||
35 | |||
36 | dma_addr_t fbdma; /* physical address */ | ||
37 | |||
38 | int rot; /* rotation enabled? */ | ||
39 | |||
40 | u32 pseudo_palette[16]; | ||
41 | |||
42 | struct platform_device *dev; | ||
43 | struct resource *ioarea; | ||
44 | struct completion vsync; /* vsync irq event */ | ||
45 | }; | ||
46 | |||
47 | static irqreturn_t sh7760fb_irq(int irq, void *data) | ||
48 | { | ||
49 | struct completion *c = data; | ||
50 | |||
51 | complete(c); | ||
52 | |||
53 | return IRQ_HANDLED; | ||
54 | } | ||
55 | |||
56 | static void sh7760fb_wait_vsync(struct fb_info *info) | ||
57 | { | ||
58 | struct sh7760fb_par *par = info->par; | ||
59 | |||
60 | if (par->pd->novsync) | ||
61 | return; | ||
62 | |||
63 | iowrite16(ioread16(par->base + LDINTR) & ~VINT_CHECK, | ||
64 | par->base + LDINTR); | ||
65 | |||
66 | if (par->irq < 0) { | ||
67 | /* poll for vert. retrace: status bit is sticky */ | ||
68 | while (!(ioread16(par->base + LDINTR) & VINT_CHECK)) | ||
69 | cpu_relax(); | ||
70 | } else { | ||
71 | /* a "wait_for_irq_event(par->irq)" would be extremely nice */ | ||
72 | init_completion(&par->vsync); | ||
73 | enable_irq(par->irq); | ||
74 | wait_for_completion(&par->vsync); | ||
75 | disable_irq_nosync(par->irq); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* wait_for_lps - wait until power supply has reached a certain state. */ | ||
80 | static int wait_for_lps(struct sh7760fb_par *par, int val) | ||
81 | { | ||
82 | int i = 100; | ||
83 | while (--i && ((ioread16(par->base + LDPMMR) & 3) != val)) | ||
84 | msleep(1); | ||
85 | |||
86 | if (i <= 0) | ||
87 | return -ETIMEDOUT; | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /* en/disable the LCDC */ | ||
93 | static int sh7760fb_blank(int blank, struct fb_info *info) | ||
94 | { | ||
95 | struct sh7760fb_par *par = info->par; | ||
96 | struct sh7760fb_platdata *pd = par->pd; | ||
97 | unsigned short cntr = ioread16(par->base + LDCNTR); | ||
98 | unsigned short intr = ioread16(par->base + LDINTR); | ||
99 | int lps; | ||
100 | |||
101 | if (blank == FB_BLANK_UNBLANK) { | ||
102 | intr |= VINT_START; | ||
103 | cntr = LDCNTR_DON2 | LDCNTR_DON; | ||
104 | lps = 3; | ||
105 | } else { | ||
106 | intr &= ~VINT_START; | ||
107 | cntr = LDCNTR_DON2; | ||
108 | lps = 0; | ||
109 | } | ||
110 | |||
111 | if (pd->blank) | ||
112 | pd->blank(blank); | ||
113 | |||
114 | iowrite16(intr, par->base + LDINTR); | ||
115 | iowrite16(cntr, par->base + LDCNTR); | ||
116 | |||
117 | return wait_for_lps(par, lps); | ||
118 | } | ||
119 | |||
120 | /* set color registers */ | ||
121 | static int sh7760fb_setcmap(struct fb_cmap *cmap, struct fb_info *info) | ||
122 | { | ||
123 | struct sh7760fb_par *par = info->par; | ||
124 | u32 s = cmap->start; | ||
125 | u32 l = cmap->len; | ||
126 | u16 *r = cmap->red; | ||
127 | u16 *g = cmap->green; | ||
128 | u16 *b = cmap->blue; | ||
129 | u32 col, tmo; | ||
130 | int ret; | ||
131 | |||
132 | ret = 0; | ||
133 | |||
134 | sh7760fb_wait_vsync(info); | ||
135 | |||
136 | /* request palette access */ | ||
137 | iowrite16(LDPALCR_PALEN, par->base + LDPALCR); | ||
138 | |||
139 | /* poll for access grant */ | ||
140 | tmo = 100; | ||
141 | while (!(ioread16(par->base + LDPALCR) & LDPALCR_PALS) && (--tmo)) | ||
142 | cpu_relax(); | ||
143 | |||
144 | if (!tmo) { | ||
145 | ret = 1; | ||
146 | dev_dbg(info->dev, "no palette access!\n"); | ||
147 | goto out; | ||
148 | } | ||
149 | |||
150 | while (l && (s < 256)) { | ||
151 | col = ((*r) & 0xff) << 16; | ||
152 | col |= ((*g) & 0xff) << 8; | ||
153 | col |= ((*b) & 0xff); | ||
154 | col &= SH7760FB_PALETTE_MASK; | ||
155 | iowrite32(col, par->base + LDPR(s)); | ||
156 | |||
157 | if (s < 16) | ||
158 | ((u32 *) (info->pseudo_palette))[s] = s; | ||
159 | |||
160 | s++; | ||
161 | l--; | ||
162 | r++; | ||
163 | g++; | ||
164 | b++; | ||
165 | } | ||
166 | out: | ||
167 | iowrite16(0, par->base + LDPALCR); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info, | ||
172 | unsigned long stride) | ||
173 | { | ||
174 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
175 | strcpy(fix->id, "sh7760-lcdc"); | ||
176 | |||
177 | fix->smem_start = (unsigned long)info->screen_base; | ||
178 | fix->smem_len = info->screen_size; | ||
179 | |||
180 | fix->line_length = stride; | ||
181 | } | ||
182 | |||
183 | static int sh7760fb_get_color_info(struct device *dev, | ||
184 | u16 lddfr, int *bpp, int *gray) | ||
185 | { | ||
186 | int lbpp, lgray; | ||
187 | |||
188 | lgray = lbpp = 0; | ||
189 | |||
190 | switch (lddfr & LDDFR_COLOR_MASK) { | ||
191 | case LDDFR_1BPP_MONO: | ||
192 | lgray = 1; | ||
193 | lbpp = 1; | ||
194 | break; | ||
195 | case LDDFR_2BPP_MONO: | ||
196 | lgray = 1; | ||
197 | lbpp = 2; | ||
198 | break; | ||
199 | case LDDFR_4BPP_MONO: | ||
200 | lgray = 1; | ||
201 | case LDDFR_4BPP: | ||
202 | lbpp = 4; | ||
203 | break; | ||
204 | case LDDFR_6BPP_MONO: | ||
205 | lgray = 1; | ||
206 | case LDDFR_8BPP: | ||
207 | lbpp = 8; | ||
208 | break; | ||
209 | case LDDFR_16BPP_RGB555: | ||
210 | case LDDFR_16BPP_RGB565: | ||
211 | lbpp = 16; | ||
212 | lgray = 0; | ||
213 | break; | ||
214 | default: | ||
215 | dev_dbg(dev, "unsupported LDDFR bit depth.\n"); | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | if (bpp) | ||
220 | *bpp = lbpp; | ||
221 | if (gray) | ||
222 | *gray = lgray; | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int sh7760fb_check_var(struct fb_var_screeninfo *var, | ||
228 | struct fb_info *info) | ||
229 | { | ||
230 | struct fb_fix_screeninfo *fix = &info->fix; | ||
231 | struct sh7760fb_par *par = info->par; | ||
232 | int ret, bpp; | ||
233 | |||
234 | /* get color info from register value */ | ||
235 | ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL); | ||
236 | if (ret) | ||
237 | return ret; | ||
238 | |||
239 | var->bits_per_pixel = bpp; | ||
240 | |||
241 | if ((var->grayscale) && (var->bits_per_pixel == 1)) | ||
242 | fix->visual = FB_VISUAL_MONO10; | ||
243 | else if (var->bits_per_pixel >= 15) | ||
244 | fix->visual = FB_VISUAL_TRUECOLOR; | ||
245 | else | ||
246 | fix->visual = FB_VISUAL_PSEUDOCOLOR; | ||
247 | |||
248 | /* TODO: add some more validation here */ | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * sh7760fb_set_par - set videomode. | ||
254 | * | ||
255 | * NOTE: The rotation, grayscale and DSTN codepaths are | ||
256 | * totally untested! | ||
257 | */ | ||
258 | static int sh7760fb_set_par(struct fb_info *info) | ||
259 | { | ||
260 | struct sh7760fb_par *par = info->par; | ||
261 | struct fb_videomode *vm = par->pd->def_mode; | ||
262 | unsigned long sbase, dstn_off, ldsarl, stride; | ||
263 | unsigned short hsynp, hsynw, htcn, hdcn; | ||
264 | unsigned short vsynp, vsynw, vtln, vdln; | ||
265 | unsigned short lddfr, ldmtr; | ||
266 | int ret, bpp, gray; | ||
267 | |||
268 | par->rot = par->pd->rotate; | ||
269 | |||
270 | /* rotate only works with xres <= 320 */ | ||
271 | if (par->rot && (vm->xres > 320)) { | ||
272 | dev_dbg(info->dev, "rotation disabled due to display size\n"); | ||
273 | par->rot = 0; | ||
274 | } | ||
275 | |||
276 | /* calculate LCDC reg vals from display parameters */ | ||
277 | hsynp = vm->right_margin + vm->xres; | ||
278 | hsynw = vm->hsync_len; | ||
279 | htcn = vm->left_margin + hsynp + hsynw; | ||
280 | hdcn = vm->xres; | ||
281 | vsynp = vm->lower_margin + vm->yres; | ||
282 | vsynw = vm->vsync_len; | ||
283 | vtln = vm->upper_margin + vsynp + vsynw; | ||
284 | vdln = vm->yres; | ||
285 | |||
286 | /* get color info from register value */ | ||
287 | ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray); | ||
288 | if (ret) | ||
289 | return ret; | ||
290 | |||
291 | dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn, | ||
292 | vdln, bpp, gray ? "grayscale" : "color", | ||
293 | par->rot ? "rotated" : "normal"); | ||
294 | |||
295 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | ||
296 | lddfr = par->pd->lddfr | (1 << 8); | ||
297 | #else | ||
298 | lddfr = par->pd->lddfr & ~(1 << 8); | ||
299 | #endif | ||
300 | |||
301 | ldmtr = par->pd->ldmtr; | ||
302 | |||
303 | if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT)) | ||
304 | ldmtr |= LDMTR_CL1POL; | ||
305 | if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT)) | ||
306 | ldmtr |= LDMTR_FLMPOL; | ||
307 | |||
308 | /* shut down LCDC before changing display parameters */ | ||
309 | sh7760fb_blank(FB_BLANK_POWERDOWN, info); | ||
310 | |||
311 | iowrite16(par->pd->ldickr, par->base + LDICKR); /* pixclock */ | ||
312 | iowrite16(ldmtr, par->base + LDMTR); /* polarities */ | ||
313 | iowrite16(lddfr, par->base + LDDFR); /* color/depth */ | ||
314 | iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR); /* rotate */ | ||
315 | iowrite16(par->pd->ldpmmr, par->base + LDPMMR); /* Power Management */ | ||
316 | iowrite16(par->pd->ldpspr, par->base + LDPSPR); /* Power Supply Ctrl */ | ||
317 | |||
318 | /* display resolution */ | ||
319 | iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8), | ||
320 | par->base + LDHCNR); | ||
321 | iowrite16(vdln - 1, par->base + LDVDLNR); | ||
322 | iowrite16(vtln - 1, par->base + LDVTLNR); | ||
323 | /* h/v sync signals */ | ||
324 | iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR); | ||
325 | iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12), | ||
326 | par->base + LDHSYNR); | ||
327 | /* AC modulation sig */ | ||
328 | iowrite16(par->pd->ldaclnr, par->base + LDACLNR); | ||
329 | |||
330 | stride = (par->rot) ? vtln : hdcn; | ||
331 | if (!gray) | ||
332 | stride *= (bpp + 7) >> 3; | ||
333 | else { | ||
334 | if (bpp == 1) | ||
335 | stride >>= 3; | ||
336 | else if (bpp == 2) | ||
337 | stride >>= 2; | ||
338 | else if (bpp == 4) | ||
339 | stride >>= 1; | ||
340 | /* 6 bpp == 8 bpp */ | ||
341 | } | ||
342 | |||
343 | /* if rotated, stride must be power of 2 */ | ||
344 | if (par->rot) { | ||
345 | unsigned long bit = 1 << 31; | ||
346 | while (bit) { | ||
347 | if (stride & bit) | ||
348 | break; | ||
349 | bit >>= 1; | ||
350 | } | ||
351 | if (stride & ~bit) | ||
352 | stride = bit << 1; /* not P-o-2, round up */ | ||
353 | } | ||
354 | iowrite16(stride, par->base + LDLAOR); | ||
355 | |||
356 | /* set display mem start address */ | ||
357 | sbase = (unsigned long)par->fbdma; | ||
358 | if (par->rot) | ||
359 | sbase += (hdcn - 1) * stride; | ||
360 | |||
361 | iowrite32(sbase, par->base + LDSARU); | ||
362 | |||
363 | /* | ||
364 | * for DSTN need to set address for lower half. | ||
365 | * I (mlau) don't know which address to set it to, | ||
366 | * so I guessed at (stride * yres/2). | ||
367 | */ | ||
368 | if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) && | ||
369 | ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) { | ||
370 | |||
371 | dev_dbg(info->dev, " ***** DSTN untested! *****\n"); | ||
372 | |||
373 | dstn_off = stride; | ||
374 | if (par->rot) | ||
375 | dstn_off *= hdcn >> 1; | ||
376 | else | ||
377 | dstn_off *= vdln >> 1; | ||
378 | |||
379 | ldsarl = sbase + dstn_off; | ||
380 | } else | ||
381 | ldsarl = 0; | ||
382 | |||
383 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ | ||
384 | |||
385 | encode_fix(&info->fix, info, stride); | ||
386 | sh7760fb_check_var(&info->var, info); | ||
387 | |||
388 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ | ||
389 | |||
390 | dev_dbg(info->dev, "hdcn : %6d htcn : %6d\n", hdcn, htcn); | ||
391 | dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp); | ||
392 | dev_dbg(info->dev, "vdln : %6d vtln : %6d\n", vdln, vtln); | ||
393 | dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp); | ||
394 | dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n", | ||
395 | (par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f); | ||
396 | dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr, | ||
397 | par->pd->ldpspr); | ||
398 | dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr); | ||
399 | dev_dbg(info->dev, "ldlaor: %ld\n", stride); | ||
400 | dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static struct fb_ops sh7760fb_ops = { | ||
406 | .owner = THIS_MODULE, | ||
407 | .fb_blank = sh7760fb_blank, | ||
408 | .fb_check_var = sh7760fb_check_var, | ||
409 | .fb_setcmap = sh7760fb_setcmap, | ||
410 | .fb_set_par = sh7760fb_set_par, | ||
411 | .fb_fillrect = cfb_fillrect, | ||
412 | .fb_copyarea = cfb_copyarea, | ||
413 | .fb_imageblit = cfb_imageblit, | ||
414 | }; | ||
415 | |||
416 | static void sh7760fb_free_mem(struct fb_info *info) | ||
417 | { | ||
418 | struct sh7760fb_par *par = info->par; | ||
419 | |||
420 | if (!info->screen_base) | ||
421 | return; | ||
422 | |||
423 | dma_free_coherent(info->dev, info->screen_size, | ||
424 | info->screen_base, par->fbdma); | ||
425 | |||
426 | par->fbdma = 0; | ||
427 | info->screen_base = NULL; | ||
428 | info->screen_size = 0; | ||
429 | } | ||
430 | |||
431 | /* allocate the framebuffer memory. This memory must be in Area3, | ||
432 | * (dictated by the DMA engine) and contiguous, at a 512 byte boundary. | ||
433 | */ | ||
434 | static int sh7760fb_alloc_mem(struct fb_info *info) | ||
435 | { | ||
436 | struct sh7760fb_par *par = info->par; | ||
437 | void *fbmem; | ||
438 | unsigned long vram; | ||
439 | int ret, bpp; | ||
440 | |||
441 | if (info->screen_base) | ||
442 | return 0; | ||
443 | |||
444 | /* get color info from register value */ | ||
445 | ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL); | ||
446 | if (ret) { | ||
447 | printk(KERN_ERR "colinfo\n"); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | /* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page | ||
452 | max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */ | ||
453 | |||
454 | vram = info->var.xres * info->var.yres; | ||
455 | if (info->var.grayscale) { | ||
456 | if (bpp == 1) | ||
457 | vram >>= 3; | ||
458 | else if (bpp == 2) | ||
459 | vram >>= 2; | ||
460 | else if (bpp == 4) | ||
461 | vram >>= 1; | ||
462 | } else if (bpp > 8) | ||
463 | vram *= 2; | ||
464 | if ((vram < 1) || (vram > 1024 * 2048)) { | ||
465 | dev_dbg(info->dev, "too much VRAM required. Check settings\n"); | ||
466 | return -ENODEV; | ||
467 | } | ||
468 | |||
469 | if (vram < PAGE_SIZE) | ||
470 | vram = PAGE_SIZE; | ||
471 | |||
472 | fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL); | ||
473 | |||
474 | if (!fbmem) | ||
475 | return -ENOMEM; | ||
476 | |||
477 | if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) { | ||
478 | sh7760fb_free_mem(info); | ||
479 | dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is" | ||
480 | "unusable for the LCDC\n", (unsigned long)par->fbdma); | ||
481 | return -ENOMEM; | ||
482 | } | ||
483 | |||
484 | info->screen_base = fbmem; | ||
485 | info->screen_size = vram; | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int __devinit sh7760fb_probe(struct platform_device *pdev) | ||
491 | { | ||
492 | struct fb_info *info; | ||
493 | struct resource *res; | ||
494 | struct sh7760fb_par *par; | ||
495 | int ret; | ||
496 | |||
497 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
498 | if (unlikely(res == NULL)) { | ||
499 | dev_err(&pdev->dev, "invalid resource\n"); | ||
500 | return -EINVAL; | ||
501 | } | ||
502 | |||
503 | info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev); | ||
504 | if (!info) | ||
505 | return -ENOMEM; | ||
506 | |||
507 | par = info->par; | ||
508 | par->dev = pdev; | ||
509 | |||
510 | par->pd = pdev->dev.platform_data; | ||
511 | if (!par->pd) { | ||
512 | dev_dbg(info->dev, "no display setup data!\n"); | ||
513 | ret = -ENODEV; | ||
514 | goto out_fb; | ||
515 | } | ||
516 | |||
517 | par->ioarea = request_mem_region(res->start, | ||
518 | (res->end - res->start), pdev->name); | ||
519 | if (!par->ioarea) { | ||
520 | dev_err(&pdev->dev, "mmio area busy\n"); | ||
521 | ret = -EBUSY; | ||
522 | goto out_fb; | ||
523 | } | ||
524 | |||
525 | par->base = ioremap_nocache(res->start, res->end - res->start + 1); | ||
526 | if (!par->base) { | ||
527 | dev_err(&pdev->dev, "cannot remap\n"); | ||
528 | ret = -ENODEV; | ||
529 | goto out_res; | ||
530 | } | ||
531 | |||
532 | iowrite16(0, par->base + LDINTR); /* disable vsync irq */ | ||
533 | par->irq = platform_get_irq(pdev, 0); | ||
534 | if (par->irq >= 0) { | ||
535 | ret = request_irq(par->irq, sh7760fb_irq, 0, | ||
536 | "sh7760-lcdc", &par->vsync); | ||
537 | if (ret) { | ||
538 | dev_err(&pdev->dev, "cannot grab IRQ\n"); | ||
539 | par->irq = -ENXIO; | ||
540 | } else | ||
541 | disable_irq_nosync(par->irq); | ||
542 | } | ||
543 | |||
544 | fb_videomode_to_var(&info->var, par->pd->def_mode); | ||
545 | |||
546 | ret = sh7760fb_alloc_mem(info); | ||
547 | if (ret) { | ||
548 | dev_dbg(info->dev, "framebuffer memory allocation failed!\n"); | ||
549 | goto out_unmap; | ||
550 | } | ||
551 | |||
552 | info->pseudo_palette = par->pseudo_palette; | ||
553 | |||
554 | /* fixup color register bitpositions. These are fixed by hardware */ | ||
555 | info->var.red.offset = 11; | ||
556 | info->var.red.length = 5; | ||
557 | info->var.red.msb_right = 0; | ||
558 | |||
559 | info->var.green.offset = 5; | ||
560 | info->var.green.length = 6; | ||
561 | info->var.green.msb_right = 0; | ||
562 | |||
563 | info->var.blue.offset = 0; | ||
564 | info->var.blue.length = 5; | ||
565 | info->var.blue.msb_right = 0; | ||
566 | |||
567 | info->var.transp.offset = 0; | ||
568 | info->var.transp.length = 0; | ||
569 | info->var.transp.msb_right = 0; | ||
570 | |||
571 | /* set the DON2 bit now, before cmap allocation, as it will randomize | ||
572 | * palette memory. | ||
573 | */ | ||
574 | iowrite16(LDCNTR_DON2, par->base + LDCNTR); | ||
575 | info->fbops = &sh7760fb_ops; | ||
576 | |||
577 | ret = fb_alloc_cmap(&info->cmap, 256, 0); | ||
578 | if (ret) { | ||
579 | dev_dbg(info->dev, "Unable to allocate cmap memory\n"); | ||
580 | goto out_mem; | ||
581 | } | ||
582 | |||
583 | ret = register_framebuffer(info); | ||
584 | if (ret < 0) { | ||
585 | dev_dbg(info->dev, "cannot register fb!\n"); | ||
586 | goto out_cmap; | ||
587 | } | ||
588 | platform_set_drvdata(pdev, info); | ||
589 | |||
590 | printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n", | ||
591 | pdev->name, | ||
592 | (unsigned long)par->fbdma, | ||
593 | (unsigned long)(par->fbdma + info->screen_size - 1), | ||
594 | info->screen_size >> 10); | ||
595 | |||
596 | return 0; | ||
597 | |||
598 | out_cmap: | ||
599 | sh7760fb_blank(FB_BLANK_POWERDOWN, info); | ||
600 | fb_dealloc_cmap(&info->cmap); | ||
601 | out_mem: | ||
602 | sh7760fb_free_mem(info); | ||
603 | out_unmap: | ||
604 | if (par->irq >= 0) | ||
605 | free_irq(par->irq, &par->vsync); | ||
606 | iounmap(par->base); | ||
607 | out_res: | ||
608 | release_resource(par->ioarea); | ||
609 | kfree(par->ioarea); | ||
610 | out_fb: | ||
611 | framebuffer_release(info); | ||
612 | return ret; | ||
613 | } | ||
614 | |||
615 | static int __devexit sh7760fb_remove(struct platform_device *dev) | ||
616 | { | ||
617 | struct fb_info *info = platform_get_drvdata(dev); | ||
618 | struct sh7760fb_par *par = info->par; | ||
619 | |||
620 | sh7760fb_blank(FB_BLANK_POWERDOWN, info); | ||
621 | unregister_framebuffer(info); | ||
622 | fb_dealloc_cmap(&info->cmap); | ||
623 | sh7760fb_free_mem(info); | ||
624 | if (par->irq >= 0) | ||
625 | free_irq(par->irq, par); | ||
626 | iounmap(par->base); | ||
627 | release_resource(par->ioarea); | ||
628 | kfree(par->ioarea); | ||
629 | framebuffer_release(info); | ||
630 | platform_set_drvdata(dev, NULL); | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | static struct platform_driver sh7760_lcdc_driver = { | ||
636 | .driver = { | ||
637 | .name = "sh7760-lcdc", | ||
638 | .owner = THIS_MODULE, | ||
639 | }, | ||
640 | .probe = sh7760fb_probe, | ||
641 | .remove = __devexit_p(sh7760fb_remove), | ||
642 | }; | ||
643 | |||
644 | static int __init sh7760fb_init(void) | ||
645 | { | ||
646 | return platform_driver_register(&sh7760_lcdc_driver); | ||
647 | } | ||
648 | |||
649 | static void __exit sh7760fb_exit(void) | ||
650 | { | ||
651 | platform_driver_unregister(&sh7760_lcdc_driver); | ||
652 | } | ||
653 | |||
654 | module_init(sh7760fb_init); | ||
655 | module_exit(sh7760fb_exit); | ||
656 | |||
657 | MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss"); | ||
658 | MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller"); | ||
659 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c new file mode 100644 index 000000000000..4c32c06579a0 --- /dev/null +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -0,0 +1,727 @@ | |||
1 | /* | ||
2 | * SuperH Mobile LCDC Framebuffer | ||
3 | * | ||
4 | * Copyright (c) 2008 Magnus Damm | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/fb.h> | ||
16 | #include <linux/clk.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <asm/sh_mobile_lcdc.h> | ||
20 | |||
21 | #define PALETTE_NR 16 | ||
22 | |||
23 | struct sh_mobile_lcdc_priv; | ||
24 | struct sh_mobile_lcdc_chan { | ||
25 | struct sh_mobile_lcdc_priv *lcdc; | ||
26 | unsigned long *reg_offs; | ||
27 | unsigned long ldmt1r_value; | ||
28 | unsigned long enabled; /* ME and SE in LDCNT2R */ | ||
29 | struct sh_mobile_lcdc_chan_cfg cfg; | ||
30 | u32 pseudo_palette[PALETTE_NR]; | ||
31 | struct fb_info info; | ||
32 | dma_addr_t dma_handle; | ||
33 | }; | ||
34 | |||
35 | struct sh_mobile_lcdc_priv { | ||
36 | void __iomem *base; | ||
37 | struct clk *clk; | ||
38 | unsigned long lddckr; | ||
39 | struct sh_mobile_lcdc_chan ch[2]; | ||
40 | }; | ||
41 | |||
42 | /* shared registers */ | ||
43 | #define _LDDCKR 0x410 | ||
44 | #define _LDDCKSTPR 0x414 | ||
45 | #define _LDINTR 0x468 | ||
46 | #define _LDSR 0x46c | ||
47 | #define _LDCNT1R 0x470 | ||
48 | #define _LDCNT2R 0x474 | ||
49 | #define _LDDDSR 0x47c | ||
50 | #define _LDDWD0R 0x800 | ||
51 | #define _LDDRDR 0x840 | ||
52 | #define _LDDWAR 0x900 | ||
53 | #define _LDDRAR 0x904 | ||
54 | |||
55 | /* per-channel registers */ | ||
56 | enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, | ||
57 | LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR }; | ||
58 | |||
59 | static unsigned long lcdc_offs_mainlcd[] = { | ||
60 | [LDDCKPAT1R] = 0x400, | ||
61 | [LDDCKPAT2R] = 0x404, | ||
62 | [LDMT1R] = 0x418, | ||
63 | [LDMT2R] = 0x41c, | ||
64 | [LDMT3R] = 0x420, | ||
65 | [LDDFR] = 0x424, | ||
66 | [LDSM1R] = 0x428, | ||
67 | [LDSA1R] = 0x430, | ||
68 | [LDMLSR] = 0x438, | ||
69 | [LDHCNR] = 0x448, | ||
70 | [LDHSYNR] = 0x44c, | ||
71 | [LDVLNR] = 0x450, | ||
72 | [LDVSYNR] = 0x454, | ||
73 | [LDPMR] = 0x460, | ||
74 | }; | ||
75 | |||
76 | static unsigned long lcdc_offs_sublcd[] = { | ||
77 | [LDDCKPAT1R] = 0x408, | ||
78 | [LDDCKPAT2R] = 0x40c, | ||
79 | [LDMT1R] = 0x600, | ||
80 | [LDMT2R] = 0x604, | ||
81 | [LDMT3R] = 0x608, | ||
82 | [LDDFR] = 0x60c, | ||
83 | [LDSM1R] = 0x610, | ||
84 | [LDSA1R] = 0x618, | ||
85 | [LDMLSR] = 0x620, | ||
86 | [LDHCNR] = 0x624, | ||
87 | [LDHSYNR] = 0x628, | ||
88 | [LDVLNR] = 0x62c, | ||
89 | [LDVSYNR] = 0x630, | ||
90 | [LDPMR] = 0x63c, | ||
91 | }; | ||
92 | |||
93 | #define START_LCDC 0x00000001 | ||
94 | #define LCDC_RESET 0x00000100 | ||
95 | #define DISPLAY_BEU 0x00000008 | ||
96 | #define LCDC_ENABLE 0x00000001 | ||
97 | |||
98 | static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, | ||
99 | int reg_nr, unsigned long data) | ||
100 | { | ||
101 | iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]); | ||
102 | } | ||
103 | |||
104 | static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, | ||
105 | int reg_nr) | ||
106 | { | ||
107 | return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]); | ||
108 | } | ||
109 | |||
110 | static void lcdc_write(struct sh_mobile_lcdc_priv *priv, | ||
111 | unsigned long reg_offs, unsigned long data) | ||
112 | { | ||
113 | iowrite32(data, priv->base + reg_offs); | ||
114 | } | ||
115 | |||
116 | static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv, | ||
117 | unsigned long reg_offs) | ||
118 | { | ||
119 | return ioread32(priv->base + reg_offs); | ||
120 | } | ||
121 | |||
122 | static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv, | ||
123 | unsigned long reg_offs, | ||
124 | unsigned long mask, unsigned long until) | ||
125 | { | ||
126 | while ((lcdc_read(priv, reg_offs) & mask) != until) | ||
127 | cpu_relax(); | ||
128 | } | ||
129 | |||
130 | static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan) | ||
131 | { | ||
132 | return chan->cfg.chan == LCDC_CHAN_SUBLCD; | ||
133 | } | ||
134 | |||
135 | static void lcdc_sys_write_index(void *handle, unsigned long data) | ||
136 | { | ||
137 | struct sh_mobile_lcdc_chan *ch = handle; | ||
138 | |||
139 | lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); | ||
140 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | ||
141 | lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | ||
142 | } | ||
143 | |||
144 | static void lcdc_sys_write_data(void *handle, unsigned long data) | ||
145 | { | ||
146 | struct sh_mobile_lcdc_chan *ch = handle; | ||
147 | |||
148 | lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); | ||
149 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | ||
150 | lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | ||
151 | } | ||
152 | |||
153 | static unsigned long lcdc_sys_read_data(void *handle) | ||
154 | { | ||
155 | struct sh_mobile_lcdc_chan *ch = handle; | ||
156 | |||
157 | lcdc_write(ch->lcdc, _LDDRDR, 0x01000000); | ||
158 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | ||
159 | lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | ||
160 | udelay(1); | ||
161 | |||
162 | return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff; | ||
163 | } | ||
164 | |||
165 | struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { | ||
166 | lcdc_sys_write_index, | ||
167 | lcdc_sys_write_data, | ||
168 | lcdc_sys_read_data, | ||
169 | }; | ||
170 | |||
171 | static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, | ||
172 | int start) | ||
173 | { | ||
174 | unsigned long tmp = lcdc_read(priv, _LDCNT2R); | ||
175 | int k; | ||
176 | |||
177 | /* start or stop the lcdc */ | ||
178 | if (start) | ||
179 | lcdc_write(priv, _LDCNT2R, tmp | START_LCDC); | ||
180 | else | ||
181 | lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC); | ||
182 | |||
183 | /* wait until power is applied/stopped on all channels */ | ||
184 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) | ||
185 | if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) | ||
186 | while (1) { | ||
187 | tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3; | ||
188 | if (start && tmp == 3) | ||
189 | break; | ||
190 | if (!start && tmp == 0) | ||
191 | break; | ||
192 | cpu_relax(); | ||
193 | } | ||
194 | |||
195 | if (!start) | ||
196 | lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ | ||
197 | } | ||
198 | |||
199 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | ||
200 | { | ||
201 | struct sh_mobile_lcdc_chan *ch; | ||
202 | struct fb_videomode *lcd_cfg; | ||
203 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
204 | unsigned long tmp; | ||
205 | int k, m; | ||
206 | int ret = 0; | ||
207 | |||
208 | /* reset */ | ||
209 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET); | ||
210 | lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0); | ||
211 | |||
212 | /* enable LCDC channels */ | ||
213 | tmp = lcdc_read(priv, _LDCNT2R); | ||
214 | tmp |= priv->ch[0].enabled; | ||
215 | tmp |= priv->ch[1].enabled; | ||
216 | lcdc_write(priv, _LDCNT2R, tmp); | ||
217 | |||
218 | /* read data from external memory, avoid using the BEU for now */ | ||
219 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU); | ||
220 | |||
221 | /* stop the lcdc first */ | ||
222 | sh_mobile_lcdc_start_stop(priv, 0); | ||
223 | |||
224 | /* configure clocks */ | ||
225 | tmp = priv->lddckr; | ||
226 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
227 | ch = &priv->ch[k]; | ||
228 | |||
229 | if (!priv->ch[k].enabled) | ||
230 | continue; | ||
231 | |||
232 | m = ch->cfg.clock_divider; | ||
233 | if (!m) | ||
234 | continue; | ||
235 | |||
236 | if (m == 1) | ||
237 | m = 1 << 6; | ||
238 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); | ||
239 | |||
240 | lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000); | ||
241 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); | ||
242 | } | ||
243 | |||
244 | lcdc_write(priv, _LDDCKR, tmp); | ||
245 | |||
246 | /* start dotclock again */ | ||
247 | lcdc_write(priv, _LDDCKSTPR, 0); | ||
248 | lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); | ||
249 | |||
250 | /* interrupts are disabled */ | ||
251 | lcdc_write(priv, _LDINTR, 0); | ||
252 | |||
253 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
254 | ch = &priv->ch[k]; | ||
255 | lcd_cfg = &ch->cfg.lcd_cfg; | ||
256 | |||
257 | if (!ch->enabled) | ||
258 | continue; | ||
259 | |||
260 | tmp = ch->ldmt1r_value; | ||
261 | tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; | ||
262 | tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; | ||
263 | lcdc_write_chan(ch, LDMT1R, tmp); | ||
264 | |||
265 | /* setup SYS bus */ | ||
266 | lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r); | ||
267 | lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); | ||
268 | |||
269 | /* horizontal configuration */ | ||
270 | tmp = lcd_cfg->xres + lcd_cfg->hsync_len; | ||
271 | tmp += lcd_cfg->left_margin; | ||
272 | tmp += lcd_cfg->right_margin; | ||
273 | tmp /= 8; /* HTCN */ | ||
274 | tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */ | ||
275 | lcdc_write_chan(ch, LDHCNR, tmp); | ||
276 | |||
277 | tmp = lcd_cfg->xres; | ||
278 | tmp += lcd_cfg->right_margin; | ||
279 | tmp /= 8; /* HSYNP */ | ||
280 | tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */ | ||
281 | lcdc_write_chan(ch, LDHSYNR, tmp); | ||
282 | |||
283 | /* power supply */ | ||
284 | lcdc_write_chan(ch, LDPMR, 0); | ||
285 | |||
286 | /* vertical configuration */ | ||
287 | tmp = lcd_cfg->yres + lcd_cfg->vsync_len; | ||
288 | tmp += lcd_cfg->upper_margin; | ||
289 | tmp += lcd_cfg->lower_margin; /* VTLN */ | ||
290 | tmp |= lcd_cfg->yres << 16; /* VDLN */ | ||
291 | lcdc_write_chan(ch, LDVLNR, tmp); | ||
292 | |||
293 | tmp = lcd_cfg->yres; | ||
294 | tmp += lcd_cfg->lower_margin; /* VSYNP */ | ||
295 | tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */ | ||
296 | lcdc_write_chan(ch, LDVSYNR, tmp); | ||
297 | |||
298 | board_cfg = &ch->cfg.board_cfg; | ||
299 | if (board_cfg->setup_sys) | ||
300 | ret = board_cfg->setup_sys(board_cfg->board_data, ch, | ||
301 | &sh_mobile_lcdc_sys_bus_ops); | ||
302 | if (ret) | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | /* --- display_lcdc_data() --- */ | ||
307 | lcdc_write(priv, _LDINTR, 0x00000f00); | ||
308 | |||
309 | /* word and long word swap */ | ||
310 | lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6); | ||
311 | |||
312 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
313 | ch = &priv->ch[k]; | ||
314 | |||
315 | if (!priv->ch[k].enabled) | ||
316 | continue; | ||
317 | |||
318 | /* set bpp format in PKF[4:0] */ | ||
319 | tmp = lcdc_read_chan(ch, LDDFR); | ||
320 | tmp &= ~(0x0001001f); | ||
321 | tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0; | ||
322 | lcdc_write_chan(ch, LDDFR, tmp); | ||
323 | |||
324 | /* point out our frame buffer */ | ||
325 | lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start); | ||
326 | |||
327 | /* set line size */ | ||
328 | lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length); | ||
329 | |||
330 | /* continuous read mode */ | ||
331 | lcdc_write_chan(ch, LDSM1R, 0); | ||
332 | } | ||
333 | |||
334 | /* display output */ | ||
335 | lcdc_write(priv, _LDCNT1R, LCDC_ENABLE); | ||
336 | |||
337 | /* start the lcdc */ | ||
338 | sh_mobile_lcdc_start_stop(priv, 1); | ||
339 | |||
340 | /* tell the board code to enable the panel */ | ||
341 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
342 | ch = &priv->ch[k]; | ||
343 | board_cfg = &ch->cfg.board_cfg; | ||
344 | if (board_cfg->display_on) | ||
345 | board_cfg->display_on(board_cfg->board_data); | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | ||
352 | { | ||
353 | struct sh_mobile_lcdc_chan *ch; | ||
354 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
355 | int k; | ||
356 | |||
357 | /* tell the board code to disable the panel */ | ||
358 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
359 | ch = &priv->ch[k]; | ||
360 | board_cfg = &ch->cfg.board_cfg; | ||
361 | if (board_cfg->display_off) | ||
362 | board_cfg->display_off(board_cfg->board_data); | ||
363 | } | ||
364 | |||
365 | /* stop the lcdc */ | ||
366 | sh_mobile_lcdc_start_stop(priv, 0); | ||
367 | } | ||
368 | |||
369 | static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) | ||
370 | { | ||
371 | int ifm, miftyp; | ||
372 | |||
373 | switch (ch->cfg.interface_type) { | ||
374 | case RGB8: ifm = 0; miftyp = 0; break; | ||
375 | case RGB9: ifm = 0; miftyp = 4; break; | ||
376 | case RGB12A: ifm = 0; miftyp = 5; break; | ||
377 | case RGB12B: ifm = 0; miftyp = 6; break; | ||
378 | case RGB16: ifm = 0; miftyp = 7; break; | ||
379 | case RGB18: ifm = 0; miftyp = 10; break; | ||
380 | case RGB24: ifm = 0; miftyp = 11; break; | ||
381 | case SYS8A: ifm = 1; miftyp = 0; break; | ||
382 | case SYS8B: ifm = 1; miftyp = 1; break; | ||
383 | case SYS8C: ifm = 1; miftyp = 2; break; | ||
384 | case SYS8D: ifm = 1; miftyp = 3; break; | ||
385 | case SYS9: ifm = 1; miftyp = 4; break; | ||
386 | case SYS12: ifm = 1; miftyp = 5; break; | ||
387 | case SYS16A: ifm = 1; miftyp = 7; break; | ||
388 | case SYS16B: ifm = 1; miftyp = 8; break; | ||
389 | case SYS16C: ifm = 1; miftyp = 9; break; | ||
390 | case SYS18: ifm = 1; miftyp = 10; break; | ||
391 | case SYS24: ifm = 1; miftyp = 11; break; | ||
392 | default: goto bad; | ||
393 | } | ||
394 | |||
395 | /* SUBLCD only supports SYS interface */ | ||
396 | if (lcdc_chan_is_sublcd(ch)) { | ||
397 | if (ifm == 0) | ||
398 | goto bad; | ||
399 | else | ||
400 | ifm = 0; | ||
401 | } | ||
402 | |||
403 | ch->ldmt1r_value = (ifm << 12) | miftyp; | ||
404 | return 0; | ||
405 | bad: | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | |||
409 | static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source, | ||
410 | struct sh_mobile_lcdc_priv *priv) | ||
411 | { | ||
412 | char *str; | ||
413 | int icksel; | ||
414 | |||
415 | switch (clock_source) { | ||
416 | case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break; | ||
417 | case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break; | ||
418 | case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break; | ||
419 | default: | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | |||
423 | priv->lddckr = icksel << 16; | ||
424 | |||
425 | if (str) { | ||
426 | priv->clk = clk_get(dev, str); | ||
427 | if (IS_ERR(priv->clk)) { | ||
428 | dev_err(dev, "cannot get clock %s\n", str); | ||
429 | return PTR_ERR(priv->clk); | ||
430 | } | ||
431 | |||
432 | clk_enable(priv->clk); | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | static int sh_mobile_lcdc_setcolreg(u_int regno, | ||
439 | u_int red, u_int green, u_int blue, | ||
440 | u_int transp, struct fb_info *info) | ||
441 | { | ||
442 | u32 *palette = info->pseudo_palette; | ||
443 | |||
444 | if (regno >= PALETTE_NR) | ||
445 | return -EINVAL; | ||
446 | |||
447 | /* only FB_VISUAL_TRUECOLOR supported */ | ||
448 | |||
449 | red >>= 16 - info->var.red.length; | ||
450 | green >>= 16 - info->var.green.length; | ||
451 | blue >>= 16 - info->var.blue.length; | ||
452 | transp >>= 16 - info->var.transp.length; | ||
453 | |||
454 | palette[regno] = (red << info->var.red.offset) | | ||
455 | (green << info->var.green.offset) | | ||
456 | (blue << info->var.blue.offset) | | ||
457 | (transp << info->var.transp.offset); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static struct fb_fix_screeninfo sh_mobile_lcdc_fix = { | ||
463 | .id = "SH Mobile LCDC", | ||
464 | .type = FB_TYPE_PACKED_PIXELS, | ||
465 | .visual = FB_VISUAL_TRUECOLOR, | ||
466 | .accel = FB_ACCEL_NONE, | ||
467 | }; | ||
468 | |||
469 | static struct fb_ops sh_mobile_lcdc_ops = { | ||
470 | .fb_setcolreg = sh_mobile_lcdc_setcolreg, | ||
471 | .fb_fillrect = cfb_fillrect, | ||
472 | .fb_copyarea = cfb_copyarea, | ||
473 | .fb_imageblit = cfb_imageblit, | ||
474 | }; | ||
475 | |||
476 | static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) | ||
477 | { | ||
478 | switch (bpp) { | ||
479 | case 16: /* PKF[4:0] = 00011 - RGB 565 */ | ||
480 | var->red.offset = 11; | ||
481 | var->red.length = 5; | ||
482 | var->green.offset = 5; | ||
483 | var->green.length = 6; | ||
484 | var->blue.offset = 0; | ||
485 | var->blue.length = 5; | ||
486 | var->transp.offset = 0; | ||
487 | var->transp.length = 0; | ||
488 | break; | ||
489 | |||
490 | case 32: /* PKF[4:0] = 00000 - RGB 888 | ||
491 | * sh7722 pdf says 00RRGGBB but reality is GGBB00RR | ||
492 | * this may be because LDDDSR has word swap enabled.. | ||
493 | */ | ||
494 | var->red.offset = 0; | ||
495 | var->red.length = 8; | ||
496 | var->green.offset = 24; | ||
497 | var->green.length = 8; | ||
498 | var->blue.offset = 16; | ||
499 | var->blue.length = 8; | ||
500 | var->transp.offset = 0; | ||
501 | var->transp.length = 0; | ||
502 | break; | ||
503 | default: | ||
504 | return -EINVAL; | ||
505 | } | ||
506 | var->bits_per_pixel = bpp; | ||
507 | var->red.msb_right = 0; | ||
508 | var->green.msb_right = 0; | ||
509 | var->blue.msb_right = 0; | ||
510 | var->transp.msb_right = 0; | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | ||
515 | |||
516 | static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) | ||
517 | { | ||
518 | struct fb_info *info; | ||
519 | struct sh_mobile_lcdc_priv *priv; | ||
520 | struct sh_mobile_lcdc_info *pdata; | ||
521 | struct sh_mobile_lcdc_chan_cfg *cfg; | ||
522 | struct resource *res; | ||
523 | int error; | ||
524 | void *buf; | ||
525 | int i, j; | ||
526 | |||
527 | if (!pdev->dev.platform_data) { | ||
528 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
529 | error = -EINVAL; | ||
530 | goto err0; | ||
531 | } | ||
532 | |||
533 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
534 | if (res == NULL) { | ||
535 | dev_err(&pdev->dev, "cannot find IO resource\n"); | ||
536 | error = -ENOENT; | ||
537 | goto err0; | ||
538 | } | ||
539 | |||
540 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
541 | if (!priv) { | ||
542 | dev_err(&pdev->dev, "cannot allocate device data\n"); | ||
543 | error = -ENOMEM; | ||
544 | goto err0; | ||
545 | } | ||
546 | |||
547 | platform_set_drvdata(pdev, priv); | ||
548 | pdata = pdev->dev.platform_data; | ||
549 | |||
550 | j = 0; | ||
551 | for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { | ||
552 | priv->ch[j].lcdc = priv; | ||
553 | memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); | ||
554 | |||
555 | error = sh_mobile_lcdc_check_interface(&priv->ch[i]); | ||
556 | if (error) { | ||
557 | dev_err(&pdev->dev, "unsupported interface type\n"); | ||
558 | goto err1; | ||
559 | } | ||
560 | |||
561 | switch (pdata->ch[i].chan) { | ||
562 | case LCDC_CHAN_MAINLCD: | ||
563 | priv->ch[j].enabled = 1 << 1; | ||
564 | priv->ch[j].reg_offs = lcdc_offs_mainlcd; | ||
565 | j++; | ||
566 | break; | ||
567 | case LCDC_CHAN_SUBLCD: | ||
568 | priv->ch[j].enabled = 1 << 2; | ||
569 | priv->ch[j].reg_offs = lcdc_offs_sublcd; | ||
570 | j++; | ||
571 | break; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | if (!j) { | ||
576 | dev_err(&pdev->dev, "no channels defined\n"); | ||
577 | error = -EINVAL; | ||
578 | goto err1; | ||
579 | } | ||
580 | |||
581 | error = sh_mobile_lcdc_setup_clocks(&pdev->dev, | ||
582 | pdata->clock_source, priv); | ||
583 | if (error) { | ||
584 | dev_err(&pdev->dev, "unable to setup clocks\n"); | ||
585 | goto err1; | ||
586 | } | ||
587 | |||
588 | priv->lddckr = pdata->lddckr; | ||
589 | priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1); | ||
590 | |||
591 | for (i = 0; i < j; i++) { | ||
592 | info = &priv->ch[i].info; | ||
593 | cfg = &priv->ch[i].cfg; | ||
594 | |||
595 | info->fbops = &sh_mobile_lcdc_ops; | ||
596 | info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; | ||
597 | info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; | ||
598 | info->var.width = cfg->lcd_size_cfg.width; | ||
599 | info->var.height = cfg->lcd_size_cfg.height; | ||
600 | info->var.activate = FB_ACTIVATE_NOW; | ||
601 | error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); | ||
602 | if (error) | ||
603 | break; | ||
604 | |||
605 | info->fix = sh_mobile_lcdc_fix; | ||
606 | info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8); | ||
607 | info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres; | ||
608 | |||
609 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, | ||
610 | &priv->ch[i].dma_handle, GFP_KERNEL); | ||
611 | if (!buf) { | ||
612 | dev_err(&pdev->dev, "unable to allocate buffer\n"); | ||
613 | error = -ENOMEM; | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | info->pseudo_palette = &priv->ch[i].pseudo_palette; | ||
618 | info->flags = FBINFO_FLAG_DEFAULT; | ||
619 | |||
620 | error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | ||
621 | if (error < 0) { | ||
622 | dev_err(&pdev->dev, "unable to allocate cmap\n"); | ||
623 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
624 | buf, priv->ch[i].dma_handle); | ||
625 | break; | ||
626 | } | ||
627 | |||
628 | memset(buf, 0, info->fix.smem_len); | ||
629 | info->fix.smem_start = priv->ch[i].dma_handle; | ||
630 | info->screen_base = buf; | ||
631 | info->device = &pdev->dev; | ||
632 | } | ||
633 | |||
634 | if (error) | ||
635 | goto err1; | ||
636 | |||
637 | error = sh_mobile_lcdc_start(priv); | ||
638 | if (error) { | ||
639 | dev_err(&pdev->dev, "unable to start hardware\n"); | ||
640 | goto err1; | ||
641 | } | ||
642 | |||
643 | for (i = 0; i < j; i++) { | ||
644 | error = register_framebuffer(&priv->ch[i].info); | ||
645 | if (error < 0) | ||
646 | goto err1; | ||
647 | } | ||
648 | |||
649 | for (i = 0; i < j; i++) { | ||
650 | info = &priv->ch[i].info; | ||
651 | dev_info(info->dev, | ||
652 | "registered %s/%s as %dx%d %dbpp.\n", | ||
653 | pdev->name, | ||
654 | (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ? | ||
655 | "mainlcd" : "sublcd", | ||
656 | (int) priv->ch[i].cfg.lcd_cfg.xres, | ||
657 | (int) priv->ch[i].cfg.lcd_cfg.yres, | ||
658 | priv->ch[i].cfg.bpp); | ||
659 | } | ||
660 | |||
661 | return 0; | ||
662 | err1: | ||
663 | sh_mobile_lcdc_remove(pdev); | ||
664 | err0: | ||
665 | return error; | ||
666 | } | ||
667 | |||
668 | static int sh_mobile_lcdc_remove(struct platform_device *pdev) | ||
669 | { | ||
670 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); | ||
671 | struct fb_info *info; | ||
672 | int i; | ||
673 | |||
674 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | ||
675 | if (priv->ch[i].info.dev) | ||
676 | unregister_framebuffer(&priv->ch[i].info); | ||
677 | |||
678 | sh_mobile_lcdc_stop(priv); | ||
679 | |||
680 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
681 | info = &priv->ch[i].info; | ||
682 | |||
683 | if (!info->device) | ||
684 | continue; | ||
685 | |||
686 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
687 | info->screen_base, priv->ch[i].dma_handle); | ||
688 | fb_dealloc_cmap(&info->cmap); | ||
689 | } | ||
690 | |||
691 | if (priv->clk) { | ||
692 | clk_disable(priv->clk); | ||
693 | clk_put(priv->clk); | ||
694 | } | ||
695 | |||
696 | if (priv->base) | ||
697 | iounmap(priv->base); | ||
698 | |||
699 | kfree(priv); | ||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static struct platform_driver sh_mobile_lcdc_driver = { | ||
704 | .driver = { | ||
705 | .name = "sh_mobile_lcdc_fb", | ||
706 | .owner = THIS_MODULE, | ||
707 | }, | ||
708 | .probe = sh_mobile_lcdc_probe, | ||
709 | .remove = sh_mobile_lcdc_remove, | ||
710 | }; | ||
711 | |||
712 | static int __init sh_mobile_lcdc_init(void) | ||
713 | { | ||
714 | return platform_driver_register(&sh_mobile_lcdc_driver); | ||
715 | } | ||
716 | |||
717 | static void __exit sh_mobile_lcdc_exit(void) | ||
718 | { | ||
719 | platform_driver_unregister(&sh_mobile_lcdc_driver); | ||
720 | } | ||
721 | |||
722 | module_init(sh_mobile_lcdc_init); | ||
723 | module_exit(sh_mobile_lcdc_exit); | ||
724 | |||
725 | MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); | ||
726 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | ||
727 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h index f40a680df86f..b96005c39c67 100644 --- a/drivers/video/sis/init.h +++ b/drivers/video/sis/init.h | |||
@@ -73,7 +73,6 @@ | |||
73 | #ifdef SIS_CP | 73 | #ifdef SIS_CP |
74 | #undef SIS_CP | 74 | #undef SIS_CP |
75 | #endif | 75 | #endif |
76 | #include <linux/version.h> | ||
77 | #include <linux/types.h> | 76 | #include <linux/types.h> |
78 | #include <asm/io.h> | 77 | #include <asm/io.h> |
79 | #include <linux/fb.h> | 78 | #include <linux/fb.h> |
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h index 7708e1e1d99e..51d99222375d 100644 --- a/drivers/video/sis/init301.h +++ b/drivers/video/sis/init301.h | |||
@@ -67,7 +67,6 @@ | |||
67 | #ifdef SIS_CP | 67 | #ifdef SIS_CP |
68 | #undef SIS_CP | 68 | #undef SIS_CP |
69 | #endif | 69 | #endif |
70 | #include <linux/version.h> | ||
71 | #include <linux/types.h> | 70 | #include <linux/types.h> |
72 | #include <asm/io.h> | 71 | #include <asm/io.h> |
73 | #include <linux/fb.h> | 72 | #include <linux/fb.h> |
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c index 47a33501549d..99c04a4855d1 100644 --- a/drivers/video/sis/initextlfb.c +++ b/drivers/video/sis/initextlfb.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include "vgatypes.h" | 30 | #include "vgatypes.h" |
31 | #include "vstruct.h" | 31 | #include "vstruct.h" |
32 | 32 | ||
33 | #include <linux/version.h> | ||
34 | #include <linux/types.h> | 33 | #include <linux/types.h> |
35 | #include <linux/fb.h> | 34 | #include <linux/fb.h> |
36 | 35 | ||
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h index c1492782cb18..6ff8f988a1a7 100644 --- a/drivers/video/sis/osdef.h +++ b/drivers/video/sis/osdef.h | |||
@@ -87,7 +87,6 @@ | |||
87 | /**********************************************************************/ | 87 | /**********************************************************************/ |
88 | 88 | ||
89 | #ifdef SIS_LINUX_KERNEL | 89 | #ifdef SIS_LINUX_KERNEL |
90 | #include <linux/version.h> | ||
91 | 90 | ||
92 | #ifdef CONFIG_FB_SIS_300 | 91 | #ifdef CONFIG_FB_SIS_300 |
93 | #define SIS300 | 92 | #define SIS300 |
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h index a14e82211037..7c5710e3fb56 100644 --- a/drivers/video/sis/sis.h +++ b/drivers/video/sis/sis.h | |||
@@ -24,8 +24,6 @@ | |||
24 | #ifndef _SIS_H_ | 24 | #ifndef _SIS_H_ |
25 | #define _SIS_H_ | 25 | #define _SIS_H_ |
26 | 26 | ||
27 | #include <linux/version.h> | ||
28 | |||
29 | #include "osdef.h" | 27 | #include "osdef.h" |
30 | #include <video/sisfb.h> | 28 | #include <video/sisfb.h> |
31 | 29 | ||
@@ -42,16 +40,6 @@ | |||
42 | #define SIS_NEW_CONFIG_COMPAT | 40 | #define SIS_NEW_CONFIG_COMPAT |
43 | #endif /* CONFIG_COMPAT */ | 41 | #endif /* CONFIG_COMPAT */ |
44 | 42 | ||
45 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) | ||
46 | #define SIS_IOTYPE1 void __iomem | ||
47 | #define SIS_IOTYPE2 __iomem | ||
48 | #define SISINITSTATIC static | ||
49 | #else | ||
50 | #define SIS_IOTYPE1 unsigned char | ||
51 | #define SIS_IOTYPE2 | ||
52 | #define SISINITSTATIC | ||
53 | #endif | ||
54 | |||
55 | #undef SISFBDEBUG | 43 | #undef SISFBDEBUG |
56 | 44 | ||
57 | #ifdef SISFBDEBUG | 45 | #ifdef SISFBDEBUG |
@@ -505,8 +493,8 @@ struct sis_video_info { | |||
505 | 493 | ||
506 | unsigned long UMAsize, LFBsize; | 494 | unsigned long UMAsize, LFBsize; |
507 | 495 | ||
508 | SIS_IOTYPE1 *video_vbase; | 496 | void __iomem *video_vbase; |
509 | SIS_IOTYPE1 *mmio_vbase; | 497 | void __iomem *mmio_vbase; |
510 | 498 | ||
511 | unsigned char *bios_abase; | 499 | unsigned char *bios_abase; |
512 | 500 | ||
@@ -533,8 +521,8 @@ struct sis_video_info { | |||
533 | int sisfb_nocrt2rate; | 521 | int sisfb_nocrt2rate; |
534 | 522 | ||
535 | u32 heapstart; /* offset */ | 523 | u32 heapstart; /* offset */ |
536 | SIS_IOTYPE1 *sisfb_heap_start; /* address */ | 524 | void __iomem *sisfb_heap_start; /* address */ |
537 | SIS_IOTYPE1 *sisfb_heap_end; /* address */ | 525 | void __iomem *sisfb_heap_end; /* address */ |
538 | u32 sisfb_heap_size; | 526 | u32 sisfb_heap_size; |
539 | int havenoheap; | 527 | int havenoheap; |
540 | 528 | ||
@@ -612,7 +600,7 @@ struct sis_video_info { | |||
612 | u8 detectedpdca; | 600 | u8 detectedpdca; |
613 | u8 detectedlcda; | 601 | u8 detectedlcda; |
614 | 602 | ||
615 | SIS_IOTYPE1 *hwcursor_vbase; | 603 | void __iomem *hwcursor_vbase; |
616 | 604 | ||
617 | int chronteltype; | 605 | int chronteltype; |
618 | int tvxpos, tvypos; | 606 | int tvxpos, tvypos; |
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c index 7addf91d2fea..ceb434c95c0d 100644 --- a/drivers/video/sis/sis_accel.c +++ b/drivers/video/sis/sis_accel.c | |||
@@ -28,7 +28,6 @@ | |||
28 | * for more information and updates) | 28 | * for more information and updates) |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
33 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
34 | #include <linux/fb.h> | 33 | #include <linux/fb.h> |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index b9343844cd1f..346d6458cf76 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -33,7 +33,6 @@ | |||
33 | * | 33 | * |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/version.h> | ||
37 | #include <linux/module.h> | 36 | #include <linux/module.h> |
38 | #include <linux/moduleparam.h> | 37 | #include <linux/moduleparam.h> |
39 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
@@ -41,13 +40,7 @@ | |||
41 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
42 | #include <linux/string.h> | 41 | #include <linux/string.h> |
43 | #include <linux/mm.h> | 42 | #include <linux/mm.h> |
44 | |||
45 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) | ||
46 | #include <linux/tty.h> | ||
47 | #else | ||
48 | #include <linux/screen_info.h> | 43 | #include <linux/screen_info.h> |
49 | #endif | ||
50 | |||
51 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
52 | #include <linux/fb.h> | 45 | #include <linux/fb.h> |
53 | #include <linux/selection.h> | 46 | #include <linux/selection.h> |
@@ -1167,11 +1160,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn) | |||
1167 | unsigned short modeno = ivideo->mode_no; | 1160 | unsigned short modeno = ivideo->mode_no; |
1168 | 1161 | ||
1169 | /* >=2.6.12's fbcon clears the screen anyway */ | 1162 | /* >=2.6.12's fbcon clears the screen anyway */ |
1170 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) | ||
1171 | if(!clrscrn) modeno |= 0x80; | ||
1172 | #else | ||
1173 | modeno |= 0x80; | 1163 | modeno |= 0x80; |
1174 | #endif | ||
1175 | 1164 | ||
1176 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); | 1165 | outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); |
1177 | 1166 | ||
@@ -1436,11 +1425,8 @@ sisfb_set_par(struct fb_info *info) | |||
1436 | if((err = sisfb_do_set_var(&info->var, 1, info))) | 1425 | if((err = sisfb_do_set_var(&info->var, 1, info))) |
1437 | return err; | 1426 | return err; |
1438 | 1427 | ||
1439 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) | ||
1440 | sisfb_get_fix(&info->fix, info->currcon, info); | ||
1441 | #else | ||
1442 | sisfb_get_fix(&info->fix, -1, info); | 1428 | sisfb_get_fix(&info->fix, -1, info); |
1443 | #endif | 1429 | |
1444 | return 0; | 1430 | return 0; |
1445 | } | 1431 | } |
1446 | 1432 | ||
@@ -1676,14 +1662,8 @@ sisfb_blank(int blank, struct fb_info *info) | |||
1676 | 1662 | ||
1677 | /* ----------- FBDev related routines for all series ---------- */ | 1663 | /* ----------- FBDev related routines for all series ---------- */ |
1678 | 1664 | ||
1679 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) | ||
1680 | static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, | 1665 | static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, |
1681 | unsigned long arg) | 1666 | unsigned long arg) |
1682 | #else | ||
1683 | static int sisfb_ioctl(struct inode *inode, struct file *file, | ||
1684 | unsigned int cmd, unsigned long arg, | ||
1685 | struct fb_info *info) | ||
1686 | #endif | ||
1687 | { | 1667 | { |
1688 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1668 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
1689 | struct sis_memreq sismemreq; | 1669 | struct sis_memreq sismemreq; |
@@ -3986,8 +3966,7 @@ sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_comm | |||
3986 | } | 3966 | } |
3987 | 3967 | ||
3988 | #ifndef MODULE | 3968 | #ifndef MODULE |
3989 | SISINITSTATIC int __init | 3969 | static int __init sisfb_setup(char *options) |
3990 | sisfb_setup(char *options) | ||
3991 | { | 3970 | { |
3992 | char *this_opt; | 3971 | char *this_opt; |
3993 | 3972 | ||
@@ -4086,9 +4065,9 @@ sisfb_setup(char *options) | |||
4086 | #endif | 4065 | #endif |
4087 | 4066 | ||
4088 | static int __devinit | 4067 | static int __devinit |
4089 | sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo) | 4068 | sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo) |
4090 | { | 4069 | { |
4091 | SIS_IOTYPE1 *rom; | 4070 | void __iomem *rom; |
4092 | int romptr; | 4071 | int romptr; |
4093 | 4072 | ||
4094 | if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) | 4073 | if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) |
@@ -4117,10 +4096,9 @@ static unsigned char * __devinit | |||
4117 | sisfb_find_rom(struct pci_dev *pdev) | 4096 | sisfb_find_rom(struct pci_dev *pdev) |
4118 | { | 4097 | { |
4119 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); | 4098 | struct sis_video_info *ivideo = pci_get_drvdata(pdev); |
4120 | SIS_IOTYPE1 *rom_base; | 4099 | void __iomem *rom_base; |
4121 | unsigned char *myrombase = NULL; | 4100 | unsigned char *myrombase = NULL; |
4122 | u32 temp; | 4101 | u32 temp; |
4123 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) | ||
4124 | size_t romsize; | 4102 | size_t romsize; |
4125 | 4103 | ||
4126 | /* First, try the official pci ROM functions (except | 4104 | /* First, try the official pci ROM functions (except |
@@ -4151,7 +4129,6 @@ sisfb_find_rom(struct pci_dev *pdev) | |||
4151 | } | 4129 | } |
4152 | 4130 | ||
4153 | if(myrombase) return myrombase; | 4131 | if(myrombase) return myrombase; |
4154 | #endif | ||
4155 | 4132 | ||
4156 | /* Otherwise do it the conventional way. */ | 4133 | /* Otherwise do it the conventional way. */ |
4157 | 4134 | ||
@@ -4225,7 +4202,7 @@ sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize, | |||
4225 | static int __devinit | 4202 | static int __devinit |
4226 | sisfb_post_300_buswidth(struct sis_video_info *ivideo) | 4203 | sisfb_post_300_buswidth(struct sis_video_info *ivideo) |
4227 | { | 4204 | { |
4228 | SIS_IOTYPE1 *FBAddress = ivideo->video_vbase; | 4205 | void __iomem *FBAddress = ivideo->video_vbase; |
4229 | unsigned short temp; | 4206 | unsigned short temp; |
4230 | unsigned char reg; | 4207 | unsigned char reg; |
4231 | int i, j; | 4208 | int i, j; |
@@ -4273,7 +4250,7 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth | |||
4273 | int PseudoRankCapacity, int PseudoAdrPinCount, | 4250 | int PseudoRankCapacity, int PseudoAdrPinCount, |
4274 | unsigned int mapsize) | 4251 | unsigned int mapsize) |
4275 | { | 4252 | { |
4276 | SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; | 4253 | void __iomem *FBAddr = ivideo->video_vbase; |
4277 | unsigned short sr14; | 4254 | unsigned short sr14; |
4278 | unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; | 4255 | unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; |
4279 | unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; | 4256 | unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; |
@@ -5829,7 +5806,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
5829 | ivideo->engineok = 0; | 5806 | ivideo->engineok = 0; |
5830 | 5807 | ||
5831 | ivideo->sisfb_was_boot_device = 0; | 5808 | ivideo->sisfb_was_boot_device = 0; |
5832 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) | 5809 | |
5833 | if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) { | 5810 | if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) { |
5834 | if(ivideo->sisvga_enabled) | 5811 | if(ivideo->sisvga_enabled) |
5835 | ivideo->sisfb_was_boot_device = 1; | 5812 | ivideo->sisfb_was_boot_device = 1; |
@@ -5840,7 +5817,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
5840 | "as the primary VGA device\n"); | 5817 | "as the primary VGA device\n"); |
5841 | } | 5818 | } |
5842 | } | 5819 | } |
5843 | #endif | ||
5844 | 5820 | ||
5845 | ivideo->sisfb_parm_mem = sisfb_parm_mem; | 5821 | ivideo->sisfb_parm_mem = sisfb_parm_mem; |
5846 | ivideo->sisfb_accel = sisfb_accel; | 5822 | ivideo->sisfb_accel = sisfb_accel; |
@@ -6010,7 +5986,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6010 | ivideo->modeprechange = reg & 0x7f; | 5986 | ivideo->modeprechange = reg & 0x7f; |
6011 | } else if(ivideo->sisvga_enabled) { | 5987 | } else if(ivideo->sisvga_enabled) { |
6012 | #if defined(__i386__) || defined(__x86_64__) | 5988 | #if defined(__i386__) || defined(__x86_64__) |
6013 | unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100); | 5989 | unsigned char __iomem *tt = ioremap(0x400, 0x100); |
6014 | if(tt) { | 5990 | if(tt) { |
6015 | ivideo->modeprechange = readb(tt + 0x49); | 5991 | ivideo->modeprechange = readb(tt + 0x49); |
6016 | iounmap(tt); | 5992 | iounmap(tt); |
@@ -6503,7 +6479,7 @@ static struct pci_driver sisfb_driver = { | |||
6503 | .remove = __devexit_p(sisfb_remove) | 6479 | .remove = __devexit_p(sisfb_remove) |
6504 | }; | 6480 | }; |
6505 | 6481 | ||
6506 | SISINITSTATIC int __init sisfb_init(void) | 6482 | static int __init sisfb_init(void) |
6507 | { | 6483 | { |
6508 | #ifndef MODULE | 6484 | #ifndef MODULE |
6509 | char *options = NULL; | 6485 | char *options = NULL; |
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h index 3e3b7fa05d6c..9540e977270e 100644 --- a/drivers/video/sis/sis_main.h +++ b/drivers/video/sis/sis_main.h | |||
@@ -665,11 +665,11 @@ static struct _customttable { | |||
665 | 665 | ||
666 | /* Interface used by the world */ | 666 | /* Interface used by the world */ |
667 | #ifndef MODULE | 667 | #ifndef MODULE |
668 | SISINITSTATIC int sisfb_setup(char *options); | 668 | static int sisfb_setup(char *options); |
669 | #endif | 669 | #endif |
670 | 670 | ||
671 | /* Interface to the low level console driver */ | 671 | /* Interface to the low level console driver */ |
672 | SISINITSTATIC int sisfb_init(void); | 672 | static int sisfb_init(void); |
673 | 673 | ||
674 | /* fbdev routines */ | 674 | /* fbdev routines */ |
675 | static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, | 675 | static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, |
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h index b532fbd2b04c..81a22eaabfde 100644 --- a/drivers/video/sis/vgatypes.h +++ b/drivers/video/sis/vgatypes.h | |||
@@ -53,10 +53,6 @@ | |||
53 | #ifndef _VGATYPES_H_ | 53 | #ifndef _VGATYPES_H_ |
54 | #define _VGATYPES_H_ | 54 | #define _VGATYPES_H_ |
55 | 55 | ||
56 | #ifdef SIS_LINUX_KERNEL | ||
57 | #include <linux/version.h> | ||
58 | #endif | ||
59 | |||
60 | #define SISIOMEMTYPE | 56 | #define SISIOMEMTYPE |
61 | 57 | ||
62 | #ifdef SIS_LINUX_KERNEL | 58 | #ifdef SIS_LINUX_KERNEL |
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 62321458f71a..df5336561d13 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
@@ -675,13 +675,13 @@ static struct fb_ops xxxfb_ops = { | |||
675 | * Initialization | 675 | * Initialization |
676 | */ | 676 | */ |
677 | 677 | ||
678 | /* static int __init xxfb_probe (struct device *device) -- for platform devs */ | 678 | /* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */ |
679 | static int __devinit xxxfb_probe(struct pci_dev *dev, | 679 | static int __devinit xxxfb_probe(struct pci_dev *dev, |
680 | const struct pci_device_id *ent) | 680 | const struct pci_device_id *ent) |
681 | { | 681 | { |
682 | struct fb_info *info; | 682 | struct fb_info *info; |
683 | struct xxx_par *par; | 683 | struct xxx_par *par; |
684 | struct device* device = &dev->dev; /* for pci drivers */ | 684 | struct device *device = &dev->dev; /* or &pdev->dev */ |
685 | int cmap_len, retval; | 685 | int cmap_len, retval; |
686 | 686 | ||
687 | /* | 687 | /* |
@@ -824,18 +824,18 @@ static int __devinit xxxfb_probe(struct pci_dev *dev, | |||
824 | return -EINVAL; | 824 | return -EINVAL; |
825 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 825 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
826 | info->fix.id); | 826 | info->fix.id); |
827 | pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */ | 827 | pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ |
828 | return 0; | 828 | return 0; |
829 | } | 829 | } |
830 | 830 | ||
831 | /* | 831 | /* |
832 | * Cleanup | 832 | * Cleanup |
833 | */ | 833 | */ |
834 | /* static void __devexit xxxfb_remove(struct device *device) */ | 834 | /* static void __devexit xxxfb_remove(struct platform_device *pdev) */ |
835 | static void __devexit xxxfb_remove(struct pci_dev *dev) | 835 | static void __devexit xxxfb_remove(struct pci_dev *dev) |
836 | { | 836 | { |
837 | struct fb_info *info = pci_get_drvdata(dev); | 837 | struct fb_info *info = pci_get_drvdata(dev); |
838 | /* or dev_get_drvdata(device); */ | 838 | /* or platform_get_drvdata(pdev); */ |
839 | 839 | ||
840 | if (info) { | 840 | if (info) { |
841 | unregister_framebuffer(info); | 841 | unregister_framebuffer(info); |
@@ -961,18 +961,17 @@ static int xxxfb_resume(struct platform_dev *dev) | |||
961 | #define xxxfb_resume NULL | 961 | #define xxxfb_resume NULL |
962 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
963 | 963 | ||
964 | static struct device_driver xxxfb_driver = { | 964 | static struct platform_device_driver xxxfb_driver = { |
965 | .name = "xxxfb", | ||
966 | .bus = &platform_bus_type, | ||
967 | .probe = xxxfb_probe, | 965 | .probe = xxxfb_probe, |
968 | .remove = xxxfb_remove, | 966 | .remove = xxxfb_remove, |
969 | .suspend = xxxfb_suspend, /* optional but recommended */ | 967 | .suspend = xxxfb_suspend, /* optional but recommended */ |
970 | .resume = xxxfb_resume, /* optional but recommended */ | 968 | .resume = xxxfb_resume, /* optional but recommended */ |
969 | .driver = { | ||
970 | .name = "xxxfb", | ||
971 | }, | ||
971 | }; | 972 | }; |
972 | 973 | ||
973 | static struct platform_device xxxfb_device = { | 974 | static struct platform_device *xxxfb_device; |
974 | .name = "xxxfb", | ||
975 | }; | ||
976 | 975 | ||
977 | #ifndef MODULE | 976 | #ifndef MODULE |
978 | /* | 977 | /* |
@@ -1002,12 +1001,16 @@ static int __init xxxfb_init(void) | |||
1002 | return -ENODEV; | 1001 | return -ENODEV; |
1003 | xxxfb_setup(option); | 1002 | xxxfb_setup(option); |
1004 | #endif | 1003 | #endif |
1005 | ret = driver_register(&xxxfb_driver); | 1004 | ret = platform_driver_register(&xxxfb_driver); |
1006 | 1005 | ||
1007 | if (!ret) { | 1006 | if (!ret) { |
1008 | ret = platform_device_register(&xxxfb_device); | 1007 | xxxfb_device = platform_device_register_simple("xxxfb", 0, |
1009 | if (ret) | 1008 | NULL, 0); |
1010 | driver_unregister(&xxxfb_driver); | 1009 | |
1010 | if (IS_ERR(xxxfb_device)) { | ||
1011 | platform_driver_unregister(&xxxfb_driver); | ||
1012 | ret = PTR_ERR(xxxfb_device); | ||
1013 | } | ||
1011 | } | 1014 | } |
1012 | 1015 | ||
1013 | return ret; | 1016 | return ret; |
@@ -1015,8 +1018,8 @@ static int __init xxxfb_init(void) | |||
1015 | 1018 | ||
1016 | static void __exit xxxfb_exit(void) | 1019 | static void __exit xxxfb_exit(void) |
1017 | { | 1020 | { |
1018 | platform_device_unregister(&xxxfb_device); | 1021 | platform_device_unregister(xxxfb_device); |
1019 | driver_unregister(&xxxfb_driver); | 1022 | platform_driver_unregister(&xxxfb_driver); |
1020 | } | 1023 | } |
1021 | #endif /* CONFIG_PCI */ | 1024 | #endif /* CONFIG_PCI */ |
1022 | 1025 | ||
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 15d4a768b1f6..f94ae84a58cd 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -48,10 +48,15 @@ enum sm501_controller { | |||
48 | HEAD_PANEL = 1, | 48 | HEAD_PANEL = 1, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* SM501 memory address */ | 51 | /* SM501 memory address. |
52 | * | ||
53 | * This structure is used to track memory usage within the SM501 framebuffer | ||
54 | * allocation. The sm_addr field is stored as an offset as it is often used | ||
55 | * against both the physical and mapped addresses. | ||
56 | */ | ||
52 | struct sm501_mem { | 57 | struct sm501_mem { |
53 | unsigned long size; | 58 | unsigned long size; |
54 | unsigned long sm_addr; | 59 | unsigned long sm_addr; /* offset from base of sm501 fb. */ |
55 | void __iomem *k_addr; | 60 | void __iomem *k_addr; |
56 | }; | 61 | }; |
57 | 62 | ||
@@ -142,31 +147,68 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) | |||
142 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | 147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, |
143 | unsigned int why, size_t size) | 148 | unsigned int why, size_t size) |
144 | { | 149 | { |
145 | unsigned int ptr = 0; | 150 | struct sm501fb_par *par; |
151 | struct fb_info *fbi; | ||
152 | unsigned int ptr; | ||
153 | unsigned int end; | ||
146 | 154 | ||
147 | switch (why) { | 155 | switch (why) { |
148 | case SM501_MEMF_CURSOR: | 156 | case SM501_MEMF_CURSOR: |
149 | ptr = inf->fbmem_len - size; | 157 | ptr = inf->fbmem_len - size; |
150 | inf->fbmem_len = ptr; | 158 | inf->fbmem_len = ptr; /* adjust available memory. */ |
151 | break; | 159 | break; |
152 | 160 | ||
153 | case SM501_MEMF_PANEL: | 161 | case SM501_MEMF_PANEL: |
154 | ptr = inf->fbmem_len - size; | 162 | ptr = inf->fbmem_len - size; |
155 | if (ptr < inf->fb[0]->fix.smem_len) | 163 | fbi = inf->fb[HEAD_CRT]; |
164 | |||
165 | /* round down, some programs such as directfb do not draw | ||
166 | * 0,0 correctly unless the start is aligned to a page start. | ||
167 | */ | ||
168 | |||
169 | if (ptr > 0) | ||
170 | ptr &= ~(PAGE_SIZE - 1); | ||
171 | |||
172 | if (fbi && ptr < fbi->fix.smem_len) | ||
173 | return -ENOMEM; | ||
174 | |||
175 | if (ptr < 0) | ||
156 | return -ENOMEM; | 176 | return -ENOMEM; |
157 | 177 | ||
158 | break; | 178 | break; |
159 | 179 | ||
160 | case SM501_MEMF_CRT: | 180 | case SM501_MEMF_CRT: |
161 | ptr = 0; | 181 | ptr = 0; |
182 | |||
183 | /* check to see if we have panel memory allocated | ||
184 | * which would put an limit on available memory. */ | ||
185 | |||
186 | fbi = inf->fb[HEAD_PANEL]; | ||
187 | if (fbi) { | ||
188 | par = fbi->par; | ||
189 | end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len; | ||
190 | } else | ||
191 | end = inf->fbmem_len; | ||
192 | |||
193 | if ((ptr + size) > end) | ||
194 | return -ENOMEM; | ||
195 | |||
162 | break; | 196 | break; |
163 | 197 | ||
164 | case SM501_MEMF_ACCEL: | 198 | case SM501_MEMF_ACCEL: |
165 | ptr = inf->fb[0]->fix.smem_len; | 199 | fbi = inf->fb[HEAD_CRT]; |
200 | ptr = fbi ? fbi->fix.smem_len : 0; | ||
201 | |||
202 | fbi = inf->fb[HEAD_PANEL]; | ||
203 | if (fbi) { | ||
204 | par = fbi->par; | ||
205 | end = par->screen.sm_addr; | ||
206 | } else | ||
207 | end = inf->fbmem_len; | ||
166 | 208 | ||
167 | if ((ptr + size) > | 209 | if ((ptr + size) > end) |
168 | (inf->fb[1]->fix.smem_start - inf->fbmem_res->start)) | ||
169 | return -ENOMEM; | 210 | return -ENOMEM; |
211 | |||
170 | break; | 212 | break; |
171 | 213 | ||
172 | default: | 214 | default: |
@@ -663,15 +705,25 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
663 | sm501fb_sync_regs(fbi); | 705 | sm501fb_sync_regs(fbi); |
664 | mdelay(10); | 706 | mdelay(10); |
665 | 707 | ||
708 | /* VBIASEN */ | ||
709 | |||
666 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { | 710 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { |
667 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ | 711 | if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN) |
712 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | ||
713 | else | ||
714 | control |= SM501_DC_PANEL_CONTROL_BIAS; | ||
715 | |||
668 | writel(control, ctrl_reg); | 716 | writel(control, ctrl_reg); |
669 | sm501fb_sync_regs(fbi); | 717 | sm501fb_sync_regs(fbi); |
670 | mdelay(10); | 718 | mdelay(10); |
671 | } | 719 | } |
672 | 720 | ||
673 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { | 721 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { |
674 | control |= SM501_DC_PANEL_CONTROL_FPEN; | 722 | if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN) |
723 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | ||
724 | else | ||
725 | control |= SM501_DC_PANEL_CONTROL_FPEN; | ||
726 | |||
675 | writel(control, ctrl_reg); | 727 | writel(control, ctrl_reg); |
676 | sm501fb_sync_regs(fbi); | 728 | sm501fb_sync_regs(fbi); |
677 | mdelay(10); | 729 | mdelay(10); |
@@ -679,14 +731,22 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
679 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { | 731 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { |
680 | /* disable panel power */ | 732 | /* disable panel power */ |
681 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { | 733 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { |
682 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | 734 | if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN) |
735 | control |= SM501_DC_PANEL_CONTROL_FPEN; | ||
736 | else | ||
737 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | ||
738 | |||
683 | writel(control, ctrl_reg); | 739 | writel(control, ctrl_reg); |
684 | sm501fb_sync_regs(fbi); | 740 | sm501fb_sync_regs(fbi); |
685 | mdelay(10); | 741 | mdelay(10); |
686 | } | 742 | } |
687 | 743 | ||
688 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { | 744 | if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { |
689 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | 745 | if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN) |
746 | control |= SM501_DC_PANEL_CONTROL_BIAS; | ||
747 | else | ||
748 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | ||
749 | |||
690 | writel(control, ctrl_reg); | 750 | writel(control, ctrl_reg); |
691 | sm501fb_sync_regs(fbi); | 751 | sm501fb_sync_regs(fbi); |
692 | mdelay(10); | 752 | mdelay(10); |
@@ -1210,39 +1270,6 @@ static struct fb_ops sm501fb_ops_pnl = { | |||
1210 | .fb_imageblit = cfb_imageblit, | 1270 | .fb_imageblit = cfb_imageblit, |
1211 | }; | 1271 | }; |
1212 | 1272 | ||
1213 | /* sm501fb_info_alloc | ||
1214 | * | ||
1215 | * creates and initialises an sm501fb_info structure | ||
1216 | */ | ||
1217 | |||
1218 | static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt, | ||
1219 | struct fb_info *fbinfo_pnl) | ||
1220 | { | ||
1221 | struct sm501fb_info *info; | ||
1222 | struct sm501fb_par *par; | ||
1223 | |||
1224 | info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL); | ||
1225 | if (info) { | ||
1226 | /* set the references back */ | ||
1227 | |||
1228 | par = fbinfo_crt->par; | ||
1229 | par->info = info; | ||
1230 | par->head = HEAD_CRT; | ||
1231 | fbinfo_crt->pseudo_palette = &par->pseudo_palette; | ||
1232 | |||
1233 | par = fbinfo_pnl->par; | ||
1234 | par->info = info; | ||
1235 | par->head = HEAD_PANEL; | ||
1236 | fbinfo_pnl->pseudo_palette = &par->pseudo_palette; | ||
1237 | |||
1238 | /* store the two fbs into our info */ | ||
1239 | info->fb[HEAD_CRT] = fbinfo_crt; | ||
1240 | info->fb[HEAD_PANEL] = fbinfo_pnl; | ||
1241 | } | ||
1242 | |||
1243 | return info; | ||
1244 | } | ||
1245 | |||
1246 | /* sm501_init_cursor | 1273 | /* sm501_init_cursor |
1247 | * | 1274 | * |
1248 | * initialise hw cursor parameters | 1275 | * initialise hw cursor parameters |
@@ -1250,10 +1277,16 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt, | |||
1250 | 1277 | ||
1251 | static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) | 1278 | static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) |
1252 | { | 1279 | { |
1253 | struct sm501fb_par *par = fbi->par; | 1280 | struct sm501fb_par *par; |
1254 | struct sm501fb_info *info = par->info; | 1281 | struct sm501fb_info *info; |
1255 | int ret; | 1282 | int ret; |
1256 | 1283 | ||
1284 | if (fbi == NULL) | ||
1285 | return 0; | ||
1286 | |||
1287 | par = fbi->par; | ||
1288 | info = par->info; | ||
1289 | |||
1257 | par->cursor_regs = info->regs + reg_base; | 1290 | par->cursor_regs = info->regs + reg_base; |
1258 | 1291 | ||
1259 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); | 1292 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); |
@@ -1281,13 +1314,10 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1281 | struct platform_device *pdev) | 1314 | struct platform_device *pdev) |
1282 | { | 1315 | { |
1283 | struct resource *res; | 1316 | struct resource *res; |
1284 | struct device *dev; | 1317 | struct device *dev = &pdev->dev; |
1285 | int k; | 1318 | int k; |
1286 | int ret; | 1319 | int ret; |
1287 | 1320 | ||
1288 | info->dev = dev = &pdev->dev; | ||
1289 | platform_set_drvdata(pdev, info); | ||
1290 | |||
1291 | info->irq = ret = platform_get_irq(pdev, 0); | 1321 | info->irq = ret = platform_get_irq(pdev, 0); |
1292 | if (ret < 0) { | 1322 | if (ret < 0) { |
1293 | /* we currently do not use the IRQ */ | 1323 | /* we currently do not use the IRQ */ |
@@ -1390,11 +1420,6 @@ static void sm501fb_stop(struct sm501fb_info *info) | |||
1390 | kfree(info->regs_res); | 1420 | kfree(info->regs_res); |
1391 | } | 1421 | } |
1392 | 1422 | ||
1393 | static void sm501fb_info_release(struct sm501fb_info *info) | ||
1394 | { | ||
1395 | kfree(info); | ||
1396 | } | ||
1397 | |||
1398 | static int sm501fb_init_fb(struct fb_info *fb, | 1423 | static int sm501fb_init_fb(struct fb_info *fb, |
1399 | enum sm501_controller head, | 1424 | enum sm501_controller head, |
1400 | const char *fbname) | 1425 | const char *fbname) |
@@ -1539,36 +1564,93 @@ static struct sm501_platdata_fb sm501fb_def_pdata = { | |||
1539 | static char driver_name_crt[] = "sm501fb-crt"; | 1564 | static char driver_name_crt[] = "sm501fb-crt"; |
1540 | static char driver_name_pnl[] = "sm501fb-panel"; | 1565 | static char driver_name_pnl[] = "sm501fb-panel"; |
1541 | 1566 | ||
1542 | static int __init sm501fb_probe(struct platform_device *pdev) | 1567 | static int __devinit sm501fb_probe_one(struct sm501fb_info *info, |
1568 | enum sm501_controller head) | ||
1543 | { | 1569 | { |
1544 | struct sm501fb_info *info; | 1570 | unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel"; |
1545 | struct device *dev = &pdev->dev; | 1571 | struct sm501_platdata_fbsub *pd; |
1546 | struct fb_info *fbinfo_crt; | 1572 | struct sm501fb_par *par; |
1547 | struct fb_info *fbinfo_pnl; | 1573 | struct fb_info *fbi; |
1548 | int ret; | ||
1549 | 1574 | ||
1550 | /* allocate our framebuffers */ | 1575 | pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl; |
1576 | |||
1577 | /* Do not initialise if we've not been given any platform data */ | ||
1578 | if (pd == NULL) { | ||
1579 | dev_info(info->dev, "no data for fb %s (disabled)\n", name); | ||
1580 | return 0; | ||
1581 | } | ||
1551 | 1582 | ||
1552 | fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev); | 1583 | fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev); |
1553 | if (fbinfo_crt == NULL) { | 1584 | if (fbi == NULL) { |
1554 | dev_err(dev, "cannot allocate crt framebuffer\n"); | 1585 | dev_err(info->dev, "cannot allocate %s framebuffer\n", name); |
1555 | return -ENOMEM; | 1586 | return -ENOMEM; |
1556 | } | 1587 | } |
1557 | 1588 | ||
1558 | fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev); | 1589 | par = fbi->par; |
1559 | if (fbinfo_pnl == NULL) { | 1590 | par->info = info; |
1560 | dev_err(dev, "cannot allocate panel framebuffer\n"); | 1591 | par->head = head; |
1561 | ret = -ENOMEM; | 1592 | fbi->pseudo_palette = &par->pseudo_palette; |
1562 | goto fbinfo_crt_alloc_fail; | 1593 | |
1594 | info->fb[head] = fbi; | ||
1595 | |||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1599 | /* Free up anything allocated by sm501fb_init_fb */ | ||
1600 | |||
1601 | static void sm501_free_init_fb(struct sm501fb_info *info, | ||
1602 | enum sm501_controller head) | ||
1603 | { | ||
1604 | struct fb_info *fbi = info->fb[head]; | ||
1605 | |||
1606 | fb_dealloc_cmap(&fbi->cmap); | ||
1607 | } | ||
1608 | |||
1609 | static int __devinit sm501fb_start_one(struct sm501fb_info *info, | ||
1610 | enum sm501_controller head, | ||
1611 | const char *drvname) | ||
1612 | { | ||
1613 | struct fb_info *fbi = info->fb[head]; | ||
1614 | int ret; | ||
1615 | |||
1616 | if (!fbi) | ||
1617 | return 0; | ||
1618 | |||
1619 | ret = sm501fb_init_fb(info->fb[head], head, drvname); | ||
1620 | if (ret) { | ||
1621 | dev_err(info->dev, "cannot initialise fb %s\n", drvname); | ||
1622 | return ret; | ||
1623 | } | ||
1624 | |||
1625 | ret = register_framebuffer(info->fb[head]); | ||
1626 | if (ret) { | ||
1627 | dev_err(info->dev, "failed to register fb %s\n", drvname); | ||
1628 | sm501_free_init_fb(info, head); | ||
1629 | return ret; | ||
1563 | } | 1630 | } |
1564 | 1631 | ||
1565 | info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl); | 1632 | dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id); |
1566 | if (info == NULL) { | 1633 | |
1567 | dev_err(dev, "cannot allocate par\n"); | 1634 | return 0; |
1568 | ret = -ENOMEM; | 1635 | } |
1569 | goto sm501fb_alloc_fail; | 1636 | |
1637 | static int __devinit sm501fb_probe(struct platform_device *pdev) | ||
1638 | { | ||
1639 | struct sm501fb_info *info; | ||
1640 | struct device *dev = &pdev->dev; | ||
1641 | int ret; | ||
1642 | |||
1643 | /* allocate our framebuffers */ | ||
1644 | |||
1645 | info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL); | ||
1646 | if (!info) { | ||
1647 | dev_err(dev, "failed to allocate state\n"); | ||
1648 | return -ENOMEM; | ||
1570 | } | 1649 | } |
1571 | 1650 | ||
1651 | info->dev = dev = &pdev->dev; | ||
1652 | platform_set_drvdata(pdev, info); | ||
1653 | |||
1572 | if (dev->parent->platform_data) { | 1654 | if (dev->parent->platform_data) { |
1573 | struct sm501_platdata *pd = dev->parent->platform_data; | 1655 | struct sm501_platdata *pd = dev->parent->platform_data; |
1574 | info->pdata = pd->fb; | 1656 | info->pdata = pd->fb; |
@@ -1579,90 +1661,88 @@ static int __init sm501fb_probe(struct platform_device *pdev) | |||
1579 | info->pdata = &sm501fb_def_pdata; | 1661 | info->pdata = &sm501fb_def_pdata; |
1580 | } | 1662 | } |
1581 | 1663 | ||
1582 | /* start the framebuffers */ | 1664 | /* probe for the presence of each panel */ |
1583 | 1665 | ||
1584 | ret = sm501fb_start(info, pdev); | 1666 | ret = sm501fb_probe_one(info, HEAD_CRT); |
1585 | if (ret) { | 1667 | if (ret < 0) { |
1586 | dev_err(dev, "cannot initialise SM501\n"); | 1668 | dev_err(dev, "failed to probe CRT\n"); |
1587 | goto sm501fb_start_fail; | 1669 | goto err_alloc; |
1588 | } | 1670 | } |
1589 | 1671 | ||
1590 | /* CRT framebuffer setup */ | 1672 | ret = sm501fb_probe_one(info, HEAD_PANEL); |
1673 | if (ret < 0) { | ||
1674 | dev_err(dev, "failed to probe PANEL\n"); | ||
1675 | goto err_probed_crt; | ||
1676 | } | ||
1591 | 1677 | ||
1592 | ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt); | 1678 | if (info->fb[HEAD_PANEL] == NULL && |
1593 | if (ret) { | 1679 | info->fb[HEAD_CRT] == NULL) { |
1594 | dev_err(dev, "cannot initialise CRT fb\n"); | 1680 | dev_err(dev, "no framebuffers found\n"); |
1595 | goto sm501fb_start_fail; | 1681 | goto err_alloc; |
1596 | } | 1682 | } |
1597 | 1683 | ||
1598 | /* Panel framebuffer setup */ | 1684 | /* get the resources for both of the framebuffers */ |
1599 | 1685 | ||
1600 | ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl); | 1686 | ret = sm501fb_start(info, pdev); |
1601 | if (ret) { | 1687 | if (ret) { |
1602 | dev_err(dev, "cannot initialise Panel fb\n"); | 1688 | dev_err(dev, "cannot initialise SM501\n"); |
1603 | goto sm501fb_start_fail; | 1689 | goto err_probed_panel; |
1604 | } | 1690 | } |
1605 | 1691 | ||
1606 | /* register framebuffers */ | 1692 | ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt); |
1607 | 1693 | if (ret) { | |
1608 | ret = register_framebuffer(fbinfo_crt); | 1694 | dev_err(dev, "failed to start CRT\n"); |
1609 | if (ret < 0) { | 1695 | goto err_started; |
1610 | dev_err(dev, "failed to register CRT fb (%d)\n", ret); | ||
1611 | goto register_crt_fail; | ||
1612 | } | 1696 | } |
1613 | 1697 | ||
1614 | ret = register_framebuffer(fbinfo_pnl); | 1698 | ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl); |
1615 | if (ret < 0) { | 1699 | if (ret) { |
1616 | dev_err(dev, "failed to register panel fb (%d)\n", ret); | 1700 | dev_err(dev, "failed to start Panel\n"); |
1617 | goto register_pnl_fail; | 1701 | goto err_started_crt; |
1618 | } | 1702 | } |
1619 | 1703 | ||
1620 | dev_info(dev, "fb%d: %s frame buffer device\n", | ||
1621 | fbinfo_crt->node, fbinfo_crt->fix.id); | ||
1622 | |||
1623 | dev_info(dev, "fb%d: %s frame buffer device\n", | ||
1624 | fbinfo_pnl->node, fbinfo_pnl->fix.id); | ||
1625 | |||
1626 | /* create device files */ | 1704 | /* create device files */ |
1627 | 1705 | ||
1628 | ret = device_create_file(dev, &dev_attr_crt_src); | 1706 | ret = device_create_file(dev, &dev_attr_crt_src); |
1629 | if (ret) | 1707 | if (ret) |
1630 | goto crtsrc_fail; | 1708 | goto err_started_panel; |
1631 | 1709 | ||
1632 | ret = device_create_file(dev, &dev_attr_fbregs_pnl); | 1710 | ret = device_create_file(dev, &dev_attr_fbregs_pnl); |
1633 | if (ret) | 1711 | if (ret) |
1634 | goto fbregs_pnl_fail; | 1712 | goto err_attached_crtsrc_file; |
1635 | 1713 | ||
1636 | ret = device_create_file(dev, &dev_attr_fbregs_crt); | 1714 | ret = device_create_file(dev, &dev_attr_fbregs_crt); |
1637 | if (ret) | 1715 | if (ret) |
1638 | goto fbregs_crt_fail; | 1716 | goto err_attached_pnlregs_file; |
1639 | 1717 | ||
1640 | /* we registered, return ok */ | 1718 | /* we registered, return ok */ |
1641 | return 0; | 1719 | return 0; |
1642 | 1720 | ||
1643 | fbregs_crt_fail: | 1721 | err_attached_pnlregs_file: |
1644 | device_remove_file(dev, &dev_attr_fbregs_pnl); | 1722 | device_remove_file(dev, &dev_attr_fbregs_pnl); |
1645 | 1723 | ||
1646 | fbregs_pnl_fail: | 1724 | err_attached_crtsrc_file: |
1647 | device_remove_file(dev, &dev_attr_crt_src); | 1725 | device_remove_file(dev, &dev_attr_crt_src); |
1648 | 1726 | ||
1649 | crtsrc_fail: | 1727 | err_started_panel: |
1650 | unregister_framebuffer(fbinfo_pnl); | 1728 | unregister_framebuffer(info->fb[HEAD_PANEL]); |
1729 | sm501_free_init_fb(info, HEAD_PANEL); | ||
1651 | 1730 | ||
1652 | register_pnl_fail: | 1731 | err_started_crt: |
1653 | unregister_framebuffer(fbinfo_crt); | 1732 | unregister_framebuffer(info->fb[HEAD_CRT]); |
1733 | sm501_free_init_fb(info, HEAD_CRT); | ||
1654 | 1734 | ||
1655 | register_crt_fail: | 1735 | err_started: |
1656 | sm501fb_stop(info); | 1736 | sm501fb_stop(info); |
1657 | 1737 | ||
1658 | sm501fb_start_fail: | 1738 | err_probed_panel: |
1659 | sm501fb_info_release(info); | 1739 | framebuffer_release(info->fb[HEAD_PANEL]); |
1660 | 1740 | ||
1661 | sm501fb_alloc_fail: | 1741 | err_probed_crt: |
1662 | framebuffer_release(fbinfo_pnl); | 1742 | framebuffer_release(info->fb[HEAD_CRT]); |
1663 | 1743 | ||
1664 | fbinfo_crt_alloc_fail: | 1744 | err_alloc: |
1665 | framebuffer_release(fbinfo_crt); | 1745 | kfree(info); |
1666 | 1746 | ||
1667 | return ret; | 1747 | return ret; |
1668 | } | 1748 | } |
@@ -1681,11 +1761,14 @@ static int sm501fb_remove(struct platform_device *pdev) | |||
1681 | device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); | 1761 | device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); |
1682 | device_remove_file(&pdev->dev, &dev_attr_crt_src); | 1762 | device_remove_file(&pdev->dev, &dev_attr_crt_src); |
1683 | 1763 | ||
1764 | sm501_free_init_fb(info, HEAD_CRT); | ||
1765 | sm501_free_init_fb(info, HEAD_PANEL); | ||
1766 | |||
1684 | unregister_framebuffer(fbinfo_crt); | 1767 | unregister_framebuffer(fbinfo_crt); |
1685 | unregister_framebuffer(fbinfo_pnl); | 1768 | unregister_framebuffer(fbinfo_pnl); |
1686 | 1769 | ||
1687 | sm501fb_stop(info); | 1770 | sm501fb_stop(info); |
1688 | sm501fb_info_release(info); | 1771 | kfree(info); |
1689 | 1772 | ||
1690 | framebuffer_release(fbinfo_pnl); | 1773 | framebuffer_release(fbinfo_pnl); |
1691 | framebuffer_release(fbinfo_crt); | 1774 | framebuffer_release(fbinfo_crt); |
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index 1a9a60c74be3..7fe5be4bc70e 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h | |||
@@ -352,8 +352,6 @@ struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ | |||
352 | 352 | ||
353 | /* functions to call the STI ROM directly */ | 353 | /* functions to call the STI ROM directly */ |
354 | 354 | ||
355 | int sti_init_graph(struct sti_struct *sti); | ||
356 | void sti_inq_conf(struct sti_struct *sti); | ||
357 | void sti_putc(struct sti_struct *sti, int c, int y, int x); | 355 | void sti_putc(struct sti_struct *sti, int c, int y, int x); |
358 | void sti_set(struct sti_struct *sti, int src_y, int src_x, | 356 | void sti_set(struct sti_struct *sti, int src_y, int src_x, |
359 | int height, int width, u8 color); | 357 | int height, int width, u8 color); |
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 598d35eff935..166481402412 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c | |||
@@ -1078,8 +1078,7 @@ static struct fb_ops stifb_ops = { | |||
1078 | * Initialization | 1078 | * Initialization |
1079 | */ | 1079 | */ |
1080 | 1080 | ||
1081 | int __init | 1081 | static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) |
1082 | stifb_init_fb(struct sti_struct *sti, int bpp_pref) | ||
1083 | { | 1082 | { |
1084 | struct fb_fix_screeninfo *fix; | 1083 | struct fb_fix_screeninfo *fix; |
1085 | struct fb_var_screeninfo *var; | 1084 | struct fb_var_screeninfo *var; |
@@ -1315,8 +1314,7 @@ static int stifb_disabled __initdata; | |||
1315 | int __init | 1314 | int __init |
1316 | stifb_setup(char *options); | 1315 | stifb_setup(char *options); |
1317 | 1316 | ||
1318 | int __init | 1317 | static int __init stifb_init(void) |
1319 | stifb_init(void) | ||
1320 | { | 1318 | { |
1321 | struct sti_struct *sti; | 1319 | struct sti_struct *sti; |
1322 | struct sti_struct *def_sti; | 1320 | struct sti_struct *def_sti; |
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index ea9f19d25597..4599a4385bc9 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -95,7 +95,6 @@ static inline int mtrr_del(int reg, unsigned long base, | |||
95 | #define VOODOO5_MAX_PIXCLOCK 350000 | 95 | #define VOODOO5_MAX_PIXCLOCK 350000 |
96 | 96 | ||
97 | static struct fb_fix_screeninfo tdfx_fix __devinitdata = { | 97 | static struct fb_fix_screeninfo tdfx_fix __devinitdata = { |
98 | .id = "3Dfx", | ||
99 | .type = FB_TYPE_PACKED_PIXELS, | 98 | .type = FB_TYPE_PACKED_PIXELS, |
100 | .visual = FB_VISUAL_PSEUDOCOLOR, | 99 | .visual = FB_VISUAL_PSEUDOCOLOR, |
101 | .ypanstep = 1, | 100 | .ypanstep = 1, |
@@ -426,7 +425,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) | |||
426 | if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) { | 425 | if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) { |
427 | /* Banshee/Voodoo3 */ | 426 | /* Banshee/Voodoo3 */ |
428 | chip_size = 2; | 427 | chip_size = 2; |
429 | if (has_sgram && (draminit0 & DRAMINIT0_SGRAM_TYPE)) | 428 | if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE)) |
430 | chip_size = 1; | 429 | chip_size = 1; |
431 | } else { | 430 | } else { |
432 | /* Voodoo4/5 */ | 431 | /* Voodoo4/5 */ |
@@ -836,16 +835,12 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var, | |||
836 | struct tdfx_par *par = info->par; | 835 | struct tdfx_par *par = info->par; |
837 | u32 addr = var->yoffset * info->fix.line_length; | 836 | u32 addr = var->yoffset * info->fix.line_length; |
838 | 837 | ||
839 | if (nopan || var->xoffset || (var->yoffset > var->yres_virtual)) | 838 | if (nopan || var->xoffset) |
840 | return -EINVAL; | ||
841 | if ((var->yoffset + var->yres > var->yres_virtual && nowrap)) | ||
842 | return -EINVAL; | 839 | return -EINVAL; |
843 | 840 | ||
844 | banshee_make_room(par, 1); | 841 | banshee_make_room(par, 1); |
845 | tdfx_outl(par, VIDDESKSTART, addr); | 842 | tdfx_outl(par, VIDDESKSTART, addr); |
846 | 843 | ||
847 | info->var.xoffset = var->xoffset; | ||
848 | info->var.yoffset = var->yoffset; | ||
849 | return 0; | 844 | return 0; |
850 | } | 845 | } |
851 | 846 | ||
@@ -1204,15 +1199,15 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, | |||
1204 | /* Configure the default fb_fix_screeninfo first */ | 1199 | /* Configure the default fb_fix_screeninfo first */ |
1205 | switch (pdev->device) { | 1200 | switch (pdev->device) { |
1206 | case PCI_DEVICE_ID_3DFX_BANSHEE: | 1201 | case PCI_DEVICE_ID_3DFX_BANSHEE: |
1207 | strcat(tdfx_fix.id, " Banshee"); | 1202 | strcpy(tdfx_fix.id, "3Dfx Banshee"); |
1208 | default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; | 1203 | default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; |
1209 | break; | 1204 | break; |
1210 | case PCI_DEVICE_ID_3DFX_VOODOO3: | 1205 | case PCI_DEVICE_ID_3DFX_VOODOO3: |
1211 | strcat(tdfx_fix.id, " Voodoo3"); | 1206 | strcpy(tdfx_fix.id, "3Dfx Voodoo3"); |
1212 | default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; | 1207 | default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; |
1213 | break; | 1208 | break; |
1214 | case PCI_DEVICE_ID_3DFX_VOODOO5: | 1209 | case PCI_DEVICE_ID_3DFX_VOODOO5: |
1215 | strcat(tdfx_fix.id, " Voodoo5"); | 1210 | strcpy(tdfx_fix.id, "3Dfx Voodoo5"); |
1216 | default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; | 1211 | default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; |
1217 | break; | 1212 | break; |
1218 | } | 1213 | } |
@@ -1426,6 +1421,8 @@ MODULE_LICENSE("GPL"); | |||
1426 | module_param(hwcursor, int, 0644); | 1421 | module_param(hwcursor, int, 0644); |
1427 | MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " | 1422 | MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " |
1428 | "(1=enable, 0=disable, default=1)"); | 1423 | "(1=enable, 0=disable, default=1)"); |
1424 | module_param(mode_option, charp, 0); | ||
1425 | MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); | ||
1429 | #ifdef CONFIG_MTRR | 1426 | #ifdef CONFIG_MTRR |
1430 | module_param(nomtrr, bool, 0); | 1427 | module_param(nomtrr, bool, 0); |
1431 | MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)"); | 1428 | MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)"); |
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index beefab2992c0..479b2e79ad68 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Frame buffer driver for Trident Blade and Image series | 2 | * Frame buffer driver for Trident TGUI, Blade and Image series |
3 | * | 3 | * |
4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> | 4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> |
5 | * | 5 | * |
@@ -13,7 +13,6 @@ | |||
13 | * code, suggestions | 13 | * code, suggestions |
14 | * TODO: | 14 | * TODO: |
15 | * timing value tweaking so it looks good on every monitor in every mode | 15 | * timing value tweaking so it looks good on every monitor in every mode |
16 | * TGUI acceleration | ||
17 | */ | 16 | */ |
18 | 17 | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
@@ -22,25 +21,26 @@ | |||
22 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
23 | 22 | ||
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <video/vga.h> | ||
25 | #include <video/trident.h> | 25 | #include <video/trident.h> |
26 | 26 | ||
27 | #define VERSION "0.7.8-NEWAPI" | ||
28 | |||
29 | struct tridentfb_par { | 27 | struct tridentfb_par { |
30 | void __iomem *io_virt; /* iospace virtual memory address */ | 28 | void __iomem *io_virt; /* iospace virtual memory address */ |
29 | u32 pseudo_pal[16]; | ||
30 | int chip_id; | ||
31 | int flatpanel; | ||
32 | void (*init_accel) (struct tridentfb_par *, int, int); | ||
33 | void (*wait_engine) (struct tridentfb_par *); | ||
34 | void (*fill_rect) | ||
35 | (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32); | ||
36 | void (*copy_rect) | ||
37 | (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32); | ||
38 | void (*image_blit) | ||
39 | (struct tridentfb_par *par, const char*, | ||
40 | u32, u32, u32, u32, u32, u32); | ||
41 | unsigned char eng_oper; /* engine operation... */ | ||
31 | }; | 42 | }; |
32 | 43 | ||
33 | static unsigned char eng_oper; /* engine operation... */ | ||
34 | static struct fb_ops tridentfb_ops; | ||
35 | |||
36 | static struct tridentfb_par default_par; | ||
37 | |||
38 | /* FIXME:kmalloc these 3 instead */ | ||
39 | static struct fb_info fb_info; | ||
40 | static u32 pseudo_pal[16]; | ||
41 | |||
42 | static struct fb_var_screeninfo default_var; | ||
43 | |||
44 | static struct fb_fix_screeninfo tridentfb_fix = { | 44 | static struct fb_fix_screeninfo tridentfb_fix = { |
45 | .id = "Trident", | 45 | .id = "Trident", |
46 | .type = FB_TYPE_PACKED_PIXELS, | 46 | .type = FB_TYPE_PACKED_PIXELS, |
@@ -49,27 +49,22 @@ static struct fb_fix_screeninfo tridentfb_fix = { | |||
49 | .accel = FB_ACCEL_NONE, | 49 | .accel = FB_ACCEL_NONE, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static int chip_id; | ||
53 | |||
54 | static int defaultaccel; | ||
55 | static int displaytype; | ||
56 | |||
57 | /* defaults which are normally overriden by user values */ | 52 | /* defaults which are normally overriden by user values */ |
58 | 53 | ||
59 | /* video mode */ | 54 | /* video mode */ |
60 | static char *mode_option __devinitdata = "640x480"; | 55 | static char *mode_option __devinitdata = "640x480-8@60"; |
61 | static int bpp = 8; | 56 | static int bpp __devinitdata = 8; |
62 | 57 | ||
63 | static int noaccel; | 58 | static int noaccel __devinitdata; |
64 | 59 | ||
65 | static int center; | 60 | static int center; |
66 | static int stretch; | 61 | static int stretch; |
67 | 62 | ||
68 | static int fp; | 63 | static int fp __devinitdata; |
69 | static int crt; | 64 | static int crt __devinitdata; |
70 | 65 | ||
71 | static int memsize; | 66 | static int memsize __devinitdata; |
72 | static int memdiff; | 67 | static int memdiff __devinitdata; |
73 | static int nativex; | 68 | static int nativex; |
74 | 69 | ||
75 | module_param(mode_option, charp, 0); | 70 | module_param(mode_option, charp, 0); |
@@ -84,25 +79,53 @@ module_param(memsize, int, 0); | |||
84 | module_param(memdiff, int, 0); | 79 | module_param(memdiff, int, 0); |
85 | module_param(nativex, int, 0); | 80 | module_param(nativex, int, 0); |
86 | module_param(fp, int, 0); | 81 | module_param(fp, int, 0); |
82 | MODULE_PARM_DESC(fp, "Define if flatpanel is connected"); | ||
87 | module_param(crt, int, 0); | 83 | module_param(crt, int, 0); |
84 | MODULE_PARM_DESC(crt, "Define if CRT is connected"); | ||
85 | |||
86 | static inline int is_oldclock(int id) | ||
87 | { | ||
88 | return (id == TGUI9440) || | ||
89 | (id == TGUI9660) || | ||
90 | (id == CYBER9320); | ||
91 | } | ||
92 | |||
93 | static inline int is_oldprotect(int id) | ||
94 | { | ||
95 | return is_oldclock(id) || | ||
96 | (id == PROVIDIA9685) || | ||
97 | (id == CYBER9382) || | ||
98 | (id == CYBER9385); | ||
99 | } | ||
100 | |||
101 | static inline int is_blade(int id) | ||
102 | { | ||
103 | return (id == BLADE3D) || | ||
104 | (id == CYBERBLADEE4) || | ||
105 | (id == CYBERBLADEi7) || | ||
106 | (id == CYBERBLADEi7D) || | ||
107 | (id == CYBERBLADEi1) || | ||
108 | (id == CYBERBLADEi1D) || | ||
109 | (id == CYBERBLADEAi1) || | ||
110 | (id == CYBERBLADEAi1D); | ||
111 | } | ||
88 | 112 | ||
89 | static int chip3D; | 113 | static inline int is_xp(int id) |
90 | static int chipcyber; | 114 | { |
115 | return (id == CYBERBLADEXPAi1) || | ||
116 | (id == CYBERBLADEXPm8) || | ||
117 | (id == CYBERBLADEXPm16); | ||
118 | } | ||
91 | 119 | ||
92 | static int is3Dchip(int id) | 120 | static inline int is3Dchip(int id) |
93 | { | 121 | { |
94 | return ((id == BLADE3D) || (id == CYBERBLADEE4) || | 122 | return is_blade(id) || is_xp(id) || |
95 | (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) || | ||
96 | (id == CYBER9397) || (id == CYBER9397DVD) || | 123 | (id == CYBER9397) || (id == CYBER9397DVD) || |
97 | (id == CYBER9520) || (id == CYBER9525DVD) || | 124 | (id == CYBER9520) || (id == CYBER9525DVD) || |
98 | (id == IMAGE975) || (id == IMAGE985) || | 125 | (id == IMAGE975) || (id == IMAGE985); |
99 | (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) || | ||
100 | (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) || | ||
101 | (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) || | ||
102 | (id == CYBERBLADEXPAi1)); | ||
103 | } | 126 | } |
104 | 127 | ||
105 | static int iscyber(int id) | 128 | static inline int iscyber(int id) |
106 | { | 129 | { |
107 | switch (id) { | 130 | switch (id) { |
108 | case CYBER9388: | 131 | case CYBER9388: |
@@ -122,12 +145,7 @@ static int iscyber(int id) | |||
122 | return 1; | 145 | return 1; |
123 | 146 | ||
124 | case CYBER9320: | 147 | case CYBER9320: |
125 | case TGUI9660: | ||
126 | case IMAGE975: | ||
127 | case IMAGE985: | ||
128 | case BLADE3D: | ||
129 | case CYBERBLADEi7: /* VIA MPV4 integrated version */ | 148 | case CYBERBLADEi7: /* VIA MPV4 integrated version */ |
130 | |||
131 | default: | 149 | default: |
132 | /* case CYBERBLDAEXPm8: Strange */ | 150 | /* case CYBERBLDAEXPm8: Strange */ |
133 | /* case CYBERBLDAEXPm16: Strange */ | 151 | /* case CYBERBLDAEXPm16: Strange */ |
@@ -135,147 +153,110 @@ static int iscyber(int id) | |||
135 | } | 153 | } |
136 | } | 154 | } |
137 | 155 | ||
138 | #define CRT 0x3D0 /* CRTC registers offset for color display */ | 156 | static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg) |
139 | 157 | { | |
140 | #ifndef TRIDENT_MMIO | 158 | fb_writeb(val, p->io_virt + reg); |
141 | #define TRIDENT_MMIO 1 | 159 | } |
142 | #endif | ||
143 | |||
144 | #if TRIDENT_MMIO | ||
145 | #define t_outb(val, reg) writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg) | ||
146 | #define t_inb(reg) readb(((struct tridentfb_par*)(fb_info.par))->io_virt + reg) | ||
147 | #else | ||
148 | #define t_outb(val, reg) outb(val, reg) | ||
149 | #define t_inb(reg) inb(reg) | ||
150 | #endif | ||
151 | 160 | ||
161 | static inline u8 t_inb(struct tridentfb_par *p, u16 reg) | ||
162 | { | ||
163 | return fb_readb(p->io_virt + reg); | ||
164 | } | ||
152 | 165 | ||
153 | static struct accel_switch { | 166 | static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v) |
154 | void (*init_accel) (int, int); | 167 | { |
155 | void (*wait_engine) (void); | 168 | fb_writel(v, par->io_virt + r); |
156 | void (*fill_rect) (u32, u32, u32, u32, u32, u32); | 169 | } |
157 | void (*copy_rect) (u32, u32, u32, u32, u32, u32); | ||
158 | } *acc; | ||
159 | 170 | ||
160 | #define writemmr(r, v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r) | 171 | static inline u32 readmmr(struct tridentfb_par *par, u16 r) |
161 | #define readmmr(r) readl(((struct tridentfb_par *)fb_info.par)->io_virt + r) | 172 | { |
173 | return fb_readl(par->io_virt + r); | ||
174 | } | ||
162 | 175 | ||
163 | /* | 176 | /* |
164 | * Blade specific acceleration. | 177 | * Blade specific acceleration. |
165 | */ | 178 | */ |
166 | 179 | ||
167 | #define point(x, y) ((y) << 16 | (x)) | 180 | #define point(x, y) ((y) << 16 | (x)) |
168 | #define STA 0x2120 | 181 | |
169 | #define CMD 0x2144 | 182 | static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
170 | #define ROP 0x2148 | ||
171 | #define CLR 0x2160 | ||
172 | #define SR1 0x2100 | ||
173 | #define SR2 0x2104 | ||
174 | #define DR1 0x2108 | ||
175 | #define DR2 0x210C | ||
176 | |||
177 | #define ROP_S 0xCC | ||
178 | |||
179 | static void blade_init_accel(int pitch, int bpp) | ||
180 | { | 183 | { |
181 | int v1 = (pitch >> 3) << 20; | 184 | int v1 = (pitch >> 3) << 20; |
182 | int tmp = 0, v2; | 185 | int tmp = bpp == 24 ? 2 : (bpp >> 4); |
183 | switch (bpp) { | 186 | int v2 = v1 | (tmp << 29); |
184 | case 8: | 187 | |
185 | tmp = 0; | 188 | writemmr(par, 0x21C0, v2); |
186 | break; | 189 | writemmr(par, 0x21C4, v2); |
187 | case 15: | 190 | writemmr(par, 0x21B8, v2); |
188 | tmp = 5; | 191 | writemmr(par, 0x21BC, v2); |
189 | break; | 192 | writemmr(par, 0x21D0, v1); |
190 | case 16: | 193 | writemmr(par, 0x21D4, v1); |
191 | tmp = 1; | 194 | writemmr(par, 0x21C8, v1); |
192 | break; | 195 | writemmr(par, 0x21CC, v1); |
193 | case 24: | 196 | writemmr(par, 0x216C, 0); |
194 | case 32: | ||
195 | tmp = 2; | ||
196 | break; | ||
197 | } | ||
198 | v2 = v1 | (tmp << 29); | ||
199 | writemmr(0x21C0, v2); | ||
200 | writemmr(0x21C4, v2); | ||
201 | writemmr(0x21B8, v2); | ||
202 | writemmr(0x21BC, v2); | ||
203 | writemmr(0x21D0, v1); | ||
204 | writemmr(0x21D4, v1); | ||
205 | writemmr(0x21C8, v1); | ||
206 | writemmr(0x21CC, v1); | ||
207 | writemmr(0x216C, 0); | ||
208 | } | 197 | } |
209 | 198 | ||
210 | static void blade_wait_engine(void) | 199 | static void blade_wait_engine(struct tridentfb_par *par) |
211 | { | 200 | { |
212 | while (readmmr(STA) & 0xFA800000) ; | 201 | while (readmmr(par, STATUS) & 0xFA800000) |
202 | cpu_relax(); | ||
213 | } | 203 | } |
214 | 204 | ||
215 | static void blade_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | 205 | static void blade_fill_rect(struct tridentfb_par *par, |
206 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | ||
216 | { | 207 | { |
217 | writemmr(CLR, c); | 208 | writemmr(par, COLOR, c); |
218 | writemmr(ROP, rop ? 0x66 : ROP_S); | 209 | writemmr(par, ROP, rop ? ROP_X : ROP_S); |
219 | writemmr(CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); | 210 | writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); |
220 | 211 | ||
221 | writemmr(DR1, point(x, y)); | 212 | writemmr(par, DST1, point(x, y)); |
222 | writemmr(DR2, point(x + w - 1, y + h - 1)); | 213 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); |
223 | } | 214 | } |
224 | 215 | ||
225 | static void blade_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | 216 | static void blade_image_blit(struct tridentfb_par *par, const char *data, |
217 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 b) | ||
218 | { | ||
219 | unsigned size = ((w + 31) >> 5) * h; | ||
220 | |||
221 | writemmr(par, COLOR, c); | ||
222 | writemmr(par, BGCOLOR, b); | ||
223 | writemmr(par, CMD, 0xa0000000 | 3 << 19); | ||
224 | |||
225 | writemmr(par, DST1, point(x, y)); | ||
226 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); | ||
227 | |||
228 | memcpy(par->io_virt + 0x10000, data, 4 * size); | ||
229 | } | ||
230 | |||
231 | static void blade_copy_rect(struct tridentfb_par *par, | ||
232 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | ||
226 | { | 233 | { |
227 | u32 s1, s2, d1, d2; | ||
228 | int direction = 2; | 234 | int direction = 2; |
229 | s1 = point(x1, y1); | 235 | u32 s1 = point(x1, y1); |
230 | s2 = point(x1 + w - 1, y1 + h - 1); | 236 | u32 s2 = point(x1 + w - 1, y1 + h - 1); |
231 | d1 = point(x2, y2); | 237 | u32 d1 = point(x2, y2); |
232 | d2 = point(x2 + w - 1, y2 + h - 1); | 238 | u32 d2 = point(x2 + w - 1, y2 + h - 1); |
233 | 239 | ||
234 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) | 240 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) |
235 | direction = 0; | 241 | direction = 0; |
236 | 242 | ||
237 | writemmr(ROP, ROP_S); | 243 | writemmr(par, ROP, ROP_S); |
238 | writemmr(CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction); | 244 | writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction); |
239 | 245 | ||
240 | writemmr(SR1, direction ? s2 : s1); | 246 | writemmr(par, SRC1, direction ? s2 : s1); |
241 | writemmr(SR2, direction ? s1 : s2); | 247 | writemmr(par, SRC2, direction ? s1 : s2); |
242 | writemmr(DR1, direction ? d2 : d1); | 248 | writemmr(par, DST1, direction ? d2 : d1); |
243 | writemmr(DR2, direction ? d1 : d2); | 249 | writemmr(par, DST2, direction ? d1 : d2); |
244 | } | 250 | } |
245 | 251 | ||
246 | static struct accel_switch accel_blade = { | ||
247 | blade_init_accel, | ||
248 | blade_wait_engine, | ||
249 | blade_fill_rect, | ||
250 | blade_copy_rect, | ||
251 | }; | ||
252 | |||
253 | /* | 252 | /* |
254 | * BladeXP specific acceleration functions | 253 | * BladeXP specific acceleration functions |
255 | */ | 254 | */ |
256 | 255 | ||
257 | #define ROP_P 0xF0 | 256 | static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
258 | #define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff)) | ||
259 | |||
260 | static void xp_init_accel(int pitch, int bpp) | ||
261 | { | 257 | { |
262 | int tmp = 0, v1; | 258 | unsigned char x = bpp == 24 ? 3 : (bpp >> 4); |
263 | unsigned char x = 0; | 259 | int v1 = pitch << (bpp == 24 ? 20 : (18 + x)); |
264 | |||
265 | switch (bpp) { | ||
266 | case 8: | ||
267 | x = 0; | ||
268 | break; | ||
269 | case 16: | ||
270 | x = 1; | ||
271 | break; | ||
272 | case 24: | ||
273 | x = 3; | ||
274 | break; | ||
275 | case 32: | ||
276 | x = 2; | ||
277 | break; | ||
278 | } | ||
279 | 260 | ||
280 | switch (pitch << (bpp >> 3)) { | 261 | switch (pitch << (bpp >> 3)) { |
281 | case 8192: | 262 | case 8192: |
@@ -293,42 +274,21 @@ static void xp_init_accel(int pitch, int bpp) | |||
293 | break; | 274 | break; |
294 | } | 275 | } |
295 | 276 | ||
296 | t_outb(x, 0x2125); | 277 | t_outb(par, x, 0x2125); |
297 | |||
298 | eng_oper = x | 0x40; | ||
299 | |||
300 | switch (bpp) { | ||
301 | case 8: | ||
302 | tmp = 18; | ||
303 | break; | ||
304 | case 15: | ||
305 | case 16: | ||
306 | tmp = 19; | ||
307 | break; | ||
308 | case 24: | ||
309 | case 32: | ||
310 | tmp = 20; | ||
311 | break; | ||
312 | } | ||
313 | 278 | ||
314 | v1 = pitch << tmp; | 279 | par->eng_oper = x | 0x40; |
315 | 280 | ||
316 | writemmr(0x2154, v1); | 281 | writemmr(par, 0x2154, v1); |
317 | writemmr(0x2150, v1); | 282 | writemmr(par, 0x2150, v1); |
318 | t_outb(3, 0x2126); | 283 | t_outb(par, 3, 0x2126); |
319 | } | 284 | } |
320 | 285 | ||
321 | static void xp_wait_engine(void) | 286 | static void xp_wait_engine(struct tridentfb_par *par) |
322 | { | 287 | { |
323 | int busy; | 288 | int count = 0; |
324 | int count, timeout; | 289 | int timeout = 0; |
325 | 290 | ||
326 | count = 0; | 291 | while (t_inb(par, STATUS) & 0x80) { |
327 | timeout = 0; | ||
328 | for (;;) { | ||
329 | busy = t_inb(STA) & 0x80; | ||
330 | if (busy != 0x80) | ||
331 | return; | ||
332 | count++; | 292 | count++; |
333 | if (count == 10000000) { | 293 | if (count == 10000000) { |
334 | /* Timeout */ | 294 | /* Timeout */ |
@@ -336,30 +296,31 @@ static void xp_wait_engine(void) | |||
336 | timeout++; | 296 | timeout++; |
337 | if (timeout == 8) { | 297 | if (timeout == 8) { |
338 | /* Reset engine */ | 298 | /* Reset engine */ |
339 | t_outb(0x00, 0x2120); | 299 | t_outb(par, 0x00, STATUS); |
340 | return; | 300 | return; |
341 | } | 301 | } |
342 | } | 302 | } |
303 | cpu_relax(); | ||
343 | } | 304 | } |
344 | } | 305 | } |
345 | 306 | ||
346 | static void xp_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | 307 | static void xp_fill_rect(struct tridentfb_par *par, |
308 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | ||
347 | { | 309 | { |
348 | writemmr(0x2127, ROP_P); | 310 | writemmr(par, 0x2127, ROP_P); |
349 | writemmr(0x2158, c); | 311 | writemmr(par, 0x2158, c); |
350 | writemmr(0x2128, 0x4000); | 312 | writemmr(par, DRAWFL, 0x4000); |
351 | writemmr(0x2140, masked_point(h, w)); | 313 | writemmr(par, OLDDIM, point(h, w)); |
352 | writemmr(0x2138, masked_point(y, x)); | 314 | writemmr(par, OLDDST, point(y, x)); |
353 | t_outb(0x01, 0x2124); | 315 | t_outb(par, 0x01, OLDCMD); |
354 | t_outb(eng_oper, 0x2125); | 316 | t_outb(par, par->eng_oper, 0x2125); |
355 | } | 317 | } |
356 | 318 | ||
357 | static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | 319 | static void xp_copy_rect(struct tridentfb_par *par, |
320 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | ||
358 | { | 321 | { |
359 | int direction; | ||
360 | u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp; | 322 | u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp; |
361 | 323 | int direction = 0x0004; | |
362 | direction = 0x0004; | ||
363 | 324 | ||
364 | if ((x1 < x2) && (y1 == y2)) { | 325 | if ((x1 < x2) && (y1 == y2)) { |
365 | direction |= 0x0200; | 326 | direction |= 0x0200; |
@@ -379,103 +340,152 @@ static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | |||
379 | y2_tmp = y2; | 340 | y2_tmp = y2; |
380 | } | 341 | } |
381 | 342 | ||
382 | writemmr(0x2128, direction); | 343 | writemmr(par, DRAWFL, direction); |
383 | t_outb(ROP_S, 0x2127); | 344 | t_outb(par, ROP_S, 0x2127); |
384 | writemmr(0x213C, masked_point(y1_tmp, x1_tmp)); | 345 | writemmr(par, OLDSRC, point(y1_tmp, x1_tmp)); |
385 | writemmr(0x2138, masked_point(y2_tmp, x2_tmp)); | 346 | writemmr(par, OLDDST, point(y2_tmp, x2_tmp)); |
386 | writemmr(0x2140, masked_point(h, w)); | 347 | writemmr(par, OLDDIM, point(h, w)); |
387 | t_outb(0x01, 0x2124); | 348 | t_outb(par, 0x01, OLDCMD); |
388 | } | 349 | } |
389 | 350 | ||
390 | static struct accel_switch accel_xp = { | ||
391 | xp_init_accel, | ||
392 | xp_wait_engine, | ||
393 | xp_fill_rect, | ||
394 | xp_copy_rect, | ||
395 | }; | ||
396 | |||
397 | /* | 351 | /* |
398 | * Image specific acceleration functions | 352 | * Image specific acceleration functions |
399 | */ | 353 | */ |
400 | static void image_init_accel(int pitch, int bpp) | 354 | static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
401 | { | 355 | { |
402 | int tmp = 0; | 356 | int tmp = bpp == 24 ? 2: (bpp >> 4); |
403 | switch (bpp) { | 357 | |
404 | case 8: | 358 | writemmr(par, 0x2120, 0xF0000000); |
405 | tmp = 0; | 359 | writemmr(par, 0x2120, 0x40000000 | tmp); |
406 | break; | 360 | writemmr(par, 0x2120, 0x80000000); |
407 | case 15: | 361 | writemmr(par, 0x2144, 0x00000000); |
408 | tmp = 5; | 362 | writemmr(par, 0x2148, 0x00000000); |
409 | break; | 363 | writemmr(par, 0x2150, 0x00000000); |
410 | case 16: | 364 | writemmr(par, 0x2154, 0x00000000); |
411 | tmp = 1; | 365 | writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch); |
412 | break; | 366 | writemmr(par, 0x216C, 0x00000000); |
413 | case 24: | 367 | writemmr(par, 0x2170, 0x00000000); |
414 | case 32: | 368 | writemmr(par, 0x217C, 0x00000000); |
415 | tmp = 2; | 369 | writemmr(par, 0x2120, 0x10000000); |
416 | break; | 370 | writemmr(par, 0x2130, (2047 << 16) | 2047); |
417 | } | ||
418 | writemmr(0x2120, 0xF0000000); | ||
419 | writemmr(0x2120, 0x40000000 | tmp); | ||
420 | writemmr(0x2120, 0x80000000); | ||
421 | writemmr(0x2144, 0x00000000); | ||
422 | writemmr(0x2148, 0x00000000); | ||
423 | writemmr(0x2150, 0x00000000); | ||
424 | writemmr(0x2154, 0x00000000); | ||
425 | writemmr(0x2120, 0x60000000 | (pitch << 16) | pitch); | ||
426 | writemmr(0x216C, 0x00000000); | ||
427 | writemmr(0x2170, 0x00000000); | ||
428 | writemmr(0x217C, 0x00000000); | ||
429 | writemmr(0x2120, 0x10000000); | ||
430 | writemmr(0x2130, (2047 << 16) | 2047); | ||
431 | } | 371 | } |
432 | 372 | ||
433 | static void image_wait_engine(void) | 373 | static void image_wait_engine(struct tridentfb_par *par) |
434 | { | 374 | { |
435 | while (readmmr(0x2164) & 0xF0000000) ; | 375 | while (readmmr(par, 0x2164) & 0xF0000000) |
376 | cpu_relax(); | ||
436 | } | 377 | } |
437 | 378 | ||
438 | static void image_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | 379 | static void image_fill_rect(struct tridentfb_par *par, |
380 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | ||
439 | { | 381 | { |
440 | writemmr(0x2120, 0x80000000); | 382 | writemmr(par, 0x2120, 0x80000000); |
441 | writemmr(0x2120, 0x90000000 | ROP_S); | 383 | writemmr(par, 0x2120, 0x90000000 | ROP_S); |
442 | 384 | ||
443 | writemmr(0x2144, c); | 385 | writemmr(par, 0x2144, c); |
444 | 386 | ||
445 | writemmr(DR1, point(x, y)); | 387 | writemmr(par, DST1, point(x, y)); |
446 | writemmr(DR2, point(x + w - 1, y + h - 1)); | 388 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); |
447 | 389 | ||
448 | writemmr(0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9); | 390 | writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9); |
449 | } | 391 | } |
450 | 392 | ||
451 | static void image_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | 393 | static void image_copy_rect(struct tridentfb_par *par, |
394 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | ||
452 | { | 395 | { |
453 | u32 s1, s2, d1, d2; | 396 | int direction = 0x4; |
454 | int direction = 2; | 397 | u32 s1 = point(x1, y1); |
455 | s1 = point(x1, y1); | 398 | u32 s2 = point(x1 + w - 1, y1 + h - 1); |
456 | s2 = point(x1 + w - 1, y1 + h - 1); | 399 | u32 d1 = point(x2, y2); |
457 | d1 = point(x2, y2); | 400 | u32 d2 = point(x2 + w - 1, y2 + h - 1); |
458 | d2 = point(x2 + w - 1, y2 + h - 1); | ||
459 | 401 | ||
460 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) | 402 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) |
461 | direction = 0; | 403 | direction = 0; |
462 | 404 | ||
463 | writemmr(0x2120, 0x80000000); | 405 | writemmr(par, 0x2120, 0x80000000); |
464 | writemmr(0x2120, 0x90000000 | ROP_S); | 406 | writemmr(par, 0x2120, 0x90000000 | ROP_S); |
465 | 407 | ||
466 | writemmr(SR1, direction ? s2 : s1); | 408 | writemmr(par, SRC1, direction ? s2 : s1); |
467 | writemmr(SR2, direction ? s1 : s2); | 409 | writemmr(par, SRC2, direction ? s1 : s2); |
468 | writemmr(DR1, direction ? d2 : d1); | 410 | writemmr(par, DST1, direction ? d2 : d1); |
469 | writemmr(DR2, direction ? d1 : d2); | 411 | writemmr(par, DST2, direction ? d1 : d2); |
470 | writemmr(0x2124, 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction); | 412 | writemmr(par, 0x2124, |
413 | 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction); | ||
471 | } | 414 | } |
472 | 415 | ||
473 | static struct accel_switch accel_image = { | 416 | /* |
474 | image_init_accel, | 417 | * TGUI 9440/96XX acceleration |
475 | image_wait_engine, | 418 | */ |
476 | image_fill_rect, | 419 | |
477 | image_copy_rect, | 420 | static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
478 | }; | 421 | { |
422 | unsigned char x = bpp == 24 ? 3 : (bpp >> 4); | ||
423 | |||
424 | /* disable clipping */ | ||
425 | writemmr(par, 0x2148, 0); | ||
426 | writemmr(par, 0x214C, point(4095, 2047)); | ||
427 | |||
428 | switch ((pitch * bpp) / 8) { | ||
429 | case 8192: | ||
430 | case 512: | ||
431 | x |= 0x00; | ||
432 | break; | ||
433 | case 1024: | ||
434 | x |= 0x04; | ||
435 | break; | ||
436 | case 2048: | ||
437 | x |= 0x08; | ||
438 | break; | ||
439 | case 4096: | ||
440 | x |= 0x0C; | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | fb_writew(x, par->io_virt + 0x2122); | ||
445 | } | ||
446 | |||
447 | static void tgui_fill_rect(struct tridentfb_par *par, | ||
448 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | ||
449 | { | ||
450 | t_outb(par, ROP_P, 0x2127); | ||
451 | writemmr(par, OLDCLR, c); | ||
452 | writemmr(par, DRAWFL, 0x4020); | ||
453 | writemmr(par, OLDDIM, point(w - 1, h - 1)); | ||
454 | writemmr(par, OLDDST, point(x, y)); | ||
455 | t_outb(par, 1, OLDCMD); | ||
456 | } | ||
457 | |||
458 | static void tgui_copy_rect(struct tridentfb_par *par, | ||
459 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | ||
460 | { | ||
461 | int flags = 0; | ||
462 | u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp; | ||
463 | |||
464 | if ((x1 < x2) && (y1 == y2)) { | ||
465 | flags |= 0x0200; | ||
466 | x1_tmp = x1 + w - 1; | ||
467 | x2_tmp = x2 + w - 1; | ||
468 | } else { | ||
469 | x1_tmp = x1; | ||
470 | x2_tmp = x2; | ||
471 | } | ||
472 | |||
473 | if (y1 < y2) { | ||
474 | flags |= 0x0100; | ||
475 | y1_tmp = y1 + h - 1; | ||
476 | y2_tmp = y2 + h - 1; | ||
477 | } else { | ||
478 | y1_tmp = y1; | ||
479 | y2_tmp = y2; | ||
480 | } | ||
481 | |||
482 | writemmr(par, DRAWFL, 0x4 | flags); | ||
483 | t_outb(par, ROP_S, 0x2127); | ||
484 | writemmr(par, OLDSRC, point(x1_tmp, y1_tmp)); | ||
485 | writemmr(par, OLDDST, point(x2_tmp, y2_tmp)); | ||
486 | writemmr(par, OLDDIM, point(w - 1, h - 1)); | ||
487 | t_outb(par, 1, OLDCMD); | ||
488 | } | ||
479 | 489 | ||
480 | /* | 490 | /* |
481 | * Accel functions called by the upper layers | 491 | * Accel functions called by the upper layers |
@@ -484,129 +494,162 @@ static struct accel_switch accel_image = { | |||
484 | static void tridentfb_fillrect(struct fb_info *info, | 494 | static void tridentfb_fillrect(struct fb_info *info, |
485 | const struct fb_fillrect *fr) | 495 | const struct fb_fillrect *fr) |
486 | { | 496 | { |
487 | int bpp = info->var.bits_per_pixel; | 497 | struct tridentfb_par *par = info->par; |
488 | int col = 0; | 498 | int col; |
489 | 499 | ||
490 | switch (bpp) { | 500 | if (info->flags & FBINFO_HWACCEL_DISABLED) { |
491 | default: | 501 | cfb_fillrect(info, fr); |
492 | case 8: | 502 | return; |
493 | col |= fr->color; | 503 | } |
504 | if (info->var.bits_per_pixel == 8) { | ||
505 | col = fr->color; | ||
494 | col |= col << 8; | 506 | col |= col << 8; |
495 | col |= col << 16; | 507 | col |= col << 16; |
496 | break; | 508 | } else |
497 | case 16: | ||
498 | col = ((u32 *)(info->pseudo_palette))[fr->color]; | 509 | col = ((u32 *)(info->pseudo_palette))[fr->color]; |
499 | break; | 510 | |
500 | case 32: | 511 | par->wait_engine(par); |
501 | col = ((u32 *)(info->pseudo_palette))[fr->color]; | 512 | par->fill_rect(par, fr->dx, fr->dy, fr->width, |
502 | break; | 513 | fr->height, col, fr->rop); |
514 | } | ||
515 | |||
516 | static void tridentfb_imageblit(struct fb_info *info, | ||
517 | const struct fb_image *img) | ||
518 | { | ||
519 | struct tridentfb_par *par = info->par; | ||
520 | int col, bgcol; | ||
521 | |||
522 | if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) { | ||
523 | cfb_imageblit(info, img); | ||
524 | return; | ||
525 | } | ||
526 | if (info->var.bits_per_pixel == 8) { | ||
527 | col = img->fg_color; | ||
528 | col |= col << 8; | ||
529 | col |= col << 16; | ||
530 | bgcol = img->bg_color; | ||
531 | bgcol |= bgcol << 8; | ||
532 | bgcol |= bgcol << 16; | ||
533 | } else { | ||
534 | col = ((u32 *)(info->pseudo_palette))[img->fg_color]; | ||
535 | bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color]; | ||
503 | } | 536 | } |
504 | 537 | ||
505 | acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop); | 538 | par->wait_engine(par); |
506 | acc->wait_engine(); | 539 | if (par->image_blit) |
540 | par->image_blit(par, img->data, img->dx, img->dy, | ||
541 | img->width, img->height, col, bgcol); | ||
542 | else | ||
543 | cfb_imageblit(info, img); | ||
507 | } | 544 | } |
545 | |||
508 | static void tridentfb_copyarea(struct fb_info *info, | 546 | static void tridentfb_copyarea(struct fb_info *info, |
509 | const struct fb_copyarea *ca) | 547 | const struct fb_copyarea *ca) |
510 | { | 548 | { |
511 | acc->copy_rect(ca->sx, ca->sy, ca->dx, ca->dy, ca->width, ca->height); | 549 | struct tridentfb_par *par = info->par; |
512 | acc->wait_engine(); | 550 | |
551 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | ||
552 | cfb_copyarea(info, ca); | ||
553 | return; | ||
554 | } | ||
555 | par->wait_engine(par); | ||
556 | par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy, | ||
557 | ca->width, ca->height); | ||
558 | } | ||
559 | |||
560 | static int tridentfb_sync(struct fb_info *info) | ||
561 | { | ||
562 | struct tridentfb_par *par = info->par; | ||
563 | |||
564 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) | ||
565 | par->wait_engine(par); | ||
566 | return 0; | ||
513 | } | 567 | } |
514 | #else /* !CONFIG_FB_TRIDENT_ACCEL */ | 568 | #else |
515 | #define tridentfb_fillrect cfb_fillrect | 569 | #define tridentfb_fillrect cfb_fillrect |
516 | #define tridentfb_copyarea cfb_copyarea | 570 | #define tridentfb_copyarea cfb_copyarea |
571 | #define tridentfb_imageblit cfb_imageblit | ||
517 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ | 572 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ |
518 | 573 | ||
519 | |||
520 | /* | 574 | /* |
521 | * Hardware access functions | 575 | * Hardware access functions |
522 | */ | 576 | */ |
523 | 577 | ||
524 | static inline unsigned char read3X4(int reg) | 578 | static inline unsigned char read3X4(struct tridentfb_par *par, int reg) |
525 | { | 579 | { |
526 | struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par; | 580 | return vga_mm_rcrt(par->io_virt, reg); |
527 | writeb(reg, par->io_virt + CRT + 4); | ||
528 | return readb(par->io_virt + CRT + 5); | ||
529 | } | 581 | } |
530 | 582 | ||
531 | static inline void write3X4(int reg, unsigned char val) | 583 | static inline void write3X4(struct tridentfb_par *par, int reg, |
584 | unsigned char val) | ||
532 | { | 585 | { |
533 | struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par; | 586 | vga_mm_wcrt(par->io_virt, reg, val); |
534 | writeb(reg, par->io_virt + CRT + 4); | ||
535 | writeb(val, par->io_virt + CRT + 5); | ||
536 | } | 587 | } |
537 | 588 | ||
538 | static inline unsigned char read3C4(int reg) | 589 | static inline unsigned char read3CE(struct tridentfb_par *par, |
590 | unsigned char reg) | ||
539 | { | 591 | { |
540 | t_outb(reg, 0x3C4); | 592 | return vga_mm_rgfx(par->io_virt, reg); |
541 | return t_inb(0x3C5); | ||
542 | } | 593 | } |
543 | 594 | ||
544 | static inline void write3C4(int reg, unsigned char val) | 595 | static inline void writeAttr(struct tridentfb_par *par, int reg, |
596 | unsigned char val) | ||
545 | { | 597 | { |
546 | t_outb(reg, 0x3C4); | 598 | fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */ |
547 | t_outb(val, 0x3C5); | 599 | vga_mm_wattr(par->io_virt, reg, val); |
548 | } | 600 | } |
549 | 601 | ||
550 | static inline unsigned char read3CE(int reg) | 602 | static inline void write3CE(struct tridentfb_par *par, int reg, |
603 | unsigned char val) | ||
551 | { | 604 | { |
552 | t_outb(reg, 0x3CE); | 605 | vga_mm_wgfx(par->io_virt, reg, val); |
553 | return t_inb(0x3CF); | ||
554 | } | 606 | } |
555 | 607 | ||
556 | static inline void writeAttr(int reg, unsigned char val) | 608 | static void enable_mmio(struct tridentfb_par *par) |
557 | { | ||
558 | readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); /* flip-flop to index */ | ||
559 | t_outb(reg, 0x3C0); | ||
560 | t_outb(val, 0x3C0); | ||
561 | } | ||
562 | |||
563 | static inline void write3CE(int reg, unsigned char val) | ||
564 | { | ||
565 | t_outb(reg, 0x3CE); | ||
566 | t_outb(val, 0x3CF); | ||
567 | } | ||
568 | |||
569 | static void enable_mmio(void) | ||
570 | { | 609 | { |
571 | /* Goto New Mode */ | 610 | /* Goto New Mode */ |
572 | outb(0x0B, 0x3C4); | 611 | vga_io_rseq(0x0B); |
573 | inb(0x3C5); | ||
574 | 612 | ||
575 | /* Unprotect registers */ | 613 | /* Unprotect registers */ |
576 | outb(NewMode1, 0x3C4); | 614 | vga_io_wseq(NewMode1, 0x80); |
577 | outb(0x80, 0x3C5); | 615 | if (!is_oldprotect(par->chip_id)) |
616 | vga_io_wseq(Protection, 0x92); | ||
578 | 617 | ||
579 | /* Enable MMIO */ | 618 | /* Enable MMIO */ |
580 | outb(PCIReg, 0x3D4); | 619 | outb(PCIReg, 0x3D4); |
581 | outb(inb(0x3D5) | 0x01, 0x3D5); | 620 | outb(inb(0x3D5) | 0x01, 0x3D5); |
582 | } | 621 | } |
583 | 622 | ||
584 | static void disable_mmio(void) | 623 | static void disable_mmio(struct tridentfb_par *par) |
585 | { | 624 | { |
586 | /* Goto New Mode */ | 625 | /* Goto New Mode */ |
587 | t_outb(0x0B, 0x3C4); | 626 | vga_mm_rseq(par->io_virt, 0x0B); |
588 | t_inb(0x3C5); | ||
589 | 627 | ||
590 | /* Unprotect registers */ | 628 | /* Unprotect registers */ |
591 | t_outb(NewMode1, 0x3C4); | 629 | vga_mm_wseq(par->io_virt, NewMode1, 0x80); |
592 | t_outb(0x80, 0x3C5); | 630 | if (!is_oldprotect(par->chip_id)) |
631 | vga_mm_wseq(par->io_virt, Protection, 0x92); | ||
593 | 632 | ||
594 | /* Disable MMIO */ | 633 | /* Disable MMIO */ |
595 | t_outb(PCIReg, 0x3D4); | 634 | t_outb(par, PCIReg, 0x3D4); |
596 | t_outb(t_inb(0x3D5) & ~0x01, 0x3D5); | 635 | t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5); |
597 | } | 636 | } |
598 | 637 | ||
599 | #define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F) | 638 | static inline void crtc_unlock(struct tridentfb_par *par) |
639 | { | ||
640 | write3X4(par, VGA_CRTC_V_SYNC_END, | ||
641 | read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F); | ||
642 | } | ||
600 | 643 | ||
601 | /* Return flat panel's maximum x resolution */ | 644 | /* Return flat panel's maximum x resolution */ |
602 | static int __devinit get_nativex(void) | 645 | static int __devinit get_nativex(struct tridentfb_par *par) |
603 | { | 646 | { |
604 | int x, y, tmp; | 647 | int x, y, tmp; |
605 | 648 | ||
606 | if (nativex) | 649 | if (nativex) |
607 | return nativex; | 650 | return nativex; |
608 | 651 | ||
609 | tmp = (read3CE(VertStretch) >> 4) & 3; | 652 | tmp = (read3CE(par, VertStretch) >> 4) & 3; |
610 | 653 | ||
611 | switch (tmp) { | 654 | switch (tmp) { |
612 | case 0: | 655 | case 0: |
@@ -632,77 +675,92 @@ static int __devinit get_nativex(void) | |||
632 | } | 675 | } |
633 | 676 | ||
634 | /* Set pitch */ | 677 | /* Set pitch */ |
635 | static void set_lwidth(int width) | 678 | static inline void set_lwidth(struct tridentfb_par *par, int width) |
636 | { | 679 | { |
637 | write3X4(Offset, width & 0xFF); | 680 | write3X4(par, VGA_CRTC_OFFSET, width & 0xFF); |
638 | write3X4(AddColReg, | 681 | write3X4(par, AddColReg, |
639 | (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >> 4)); | 682 | (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4)); |
640 | } | 683 | } |
641 | 684 | ||
642 | /* For resolutions smaller than FP resolution stretch */ | 685 | /* For resolutions smaller than FP resolution stretch */ |
643 | static void screen_stretch(void) | 686 | static void screen_stretch(struct tridentfb_par *par) |
644 | { | 687 | { |
645 | if (chip_id != CYBERBLADEXPAi1) | 688 | if (par->chip_id != CYBERBLADEXPAi1) |
646 | write3CE(BiosReg, 0); | 689 | write3CE(par, BiosReg, 0); |
647 | else | 690 | else |
648 | write3CE(BiosReg, 8); | 691 | write3CE(par, BiosReg, 8); |
649 | write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 1); | 692 | write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1); |
650 | write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 1); | 693 | write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1); |
651 | } | 694 | } |
652 | 695 | ||
653 | /* For resolutions smaller than FP resolution center */ | 696 | /* For resolutions smaller than FP resolution center */ |
654 | static void screen_center(void) | 697 | static inline void screen_center(struct tridentfb_par *par) |
655 | { | 698 | { |
656 | write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 0x80); | 699 | write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80); |
657 | write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 0x80); | 700 | write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80); |
658 | } | 701 | } |
659 | 702 | ||
660 | /* Address of first shown pixel in display memory */ | 703 | /* Address of first shown pixel in display memory */ |
661 | static void set_screen_start(int base) | 704 | static void set_screen_start(struct tridentfb_par *par, int base) |
662 | { | 705 | { |
663 | write3X4(StartAddrLow, base & 0xFF); | 706 | u8 tmp; |
664 | write3X4(StartAddrHigh, (base & 0xFF00) >> 8); | 707 | write3X4(par, VGA_CRTC_START_LO, base & 0xFF); |
665 | write3X4(CRTCModuleTest, | 708 | write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8); |
666 | (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11)); | 709 | tmp = read3X4(par, CRTCModuleTest) & 0xDF; |
667 | write3X4(CRTHiOrd, | 710 | write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11)); |
668 | (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17)); | 711 | tmp = read3X4(par, CRTHiOrd) & 0xF8; |
712 | write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17)); | ||
669 | } | 713 | } |
670 | 714 | ||
671 | /* Set dotclock frequency */ | 715 | /* Set dotclock frequency */ |
672 | static void set_vclk(unsigned long freq) | 716 | static void set_vclk(struct tridentfb_par *par, unsigned long freq) |
673 | { | 717 | { |
674 | int m, n, k; | 718 | int m, n, k; |
675 | unsigned long f, fi, d, di; | 719 | unsigned long fi, d, di; |
676 | unsigned char lo = 0, hi = 0; | 720 | unsigned char best_m = 0, best_n = 0, best_k = 0; |
721 | unsigned char hi, lo; | ||
722 | unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1; | ||
677 | 723 | ||
678 | d = 20000; | 724 | d = 20000; |
679 | for (k = 2; k >= 0; k--) | 725 | for (k = shift; k >= 0; k--) |
680 | for (m = 0; m < 63; m++) | 726 | for (m = 1; m < 32; m++) { |
681 | for (n = 0; n < 128; n++) { | 727 | n = ((m + 2) << shift) - 8; |
728 | for (n = (n < 0 ? 0 : n); n < 122; n++) { | ||
682 | fi = ((14318l * (n + 8)) / (m + 2)) >> k; | 729 | fi = ((14318l * (n + 8)) / (m + 2)) >> k; |
683 | if ((di = abs(fi - freq)) < d) { | 730 | di = abs(fi - freq); |
731 | if (di < d || (di == d && k == best_k)) { | ||
684 | d = di; | 732 | d = di; |
685 | f = fi; | 733 | best_n = n; |
686 | lo = n; | 734 | best_m = m; |
687 | hi = (k << 6) | m; | 735 | best_k = k; |
688 | } | 736 | } |
689 | if (fi > freq) | 737 | if (fi > freq) |
690 | break; | 738 | break; |
691 | } | 739 | } |
692 | if (chip3D) { | 740 | } |
693 | write3C4(ClockHigh, hi); | 741 | |
694 | write3C4(ClockLow, lo); | 742 | if (is_oldclock(par->chip_id)) { |
743 | lo = best_n | (best_m << 7); | ||
744 | hi = (best_m >> 1) | (best_k << 4); | ||
695 | } else { | 745 | } else { |
696 | outb(lo, 0x43C8); | 746 | lo = best_n; |
697 | outb(hi, 0x43C9); | 747 | hi = best_m | (best_k << 6); |
748 | } | ||
749 | |||
750 | if (is3Dchip(par->chip_id)) { | ||
751 | vga_mm_wseq(par->io_virt, ClockHigh, hi); | ||
752 | vga_mm_wseq(par->io_virt, ClockLow, lo); | ||
753 | } else { | ||
754 | t_outb(par, lo, 0x43C8); | ||
755 | t_outb(par, hi, 0x43C9); | ||
698 | } | 756 | } |
699 | debug("VCLK = %X %X\n", hi, lo); | 757 | debug("VCLK = %X %X\n", hi, lo); |
700 | } | 758 | } |
701 | 759 | ||
702 | /* Set number of lines for flat panels*/ | 760 | /* Set number of lines for flat panels*/ |
703 | static void set_number_of_lines(int lines) | 761 | static void set_number_of_lines(struct tridentfb_par *par, int lines) |
704 | { | 762 | { |
705 | int tmp = read3CE(CyberEnhance) & 0x8F; | 763 | int tmp = read3CE(par, CyberEnhance) & 0x8F; |
706 | if (lines > 1024) | 764 | if (lines > 1024) |
707 | tmp |= 0x50; | 765 | tmp |= 0x50; |
708 | else if (lines > 768) | 766 | else if (lines > 768) |
@@ -711,24 +769,24 @@ static void set_number_of_lines(int lines) | |||
711 | tmp |= 0x20; | 769 | tmp |= 0x20; |
712 | else if (lines > 480) | 770 | else if (lines > 480) |
713 | tmp |= 0x10; | 771 | tmp |= 0x10; |
714 | write3CE(CyberEnhance, tmp); | 772 | write3CE(par, CyberEnhance, tmp); |
715 | } | 773 | } |
716 | 774 | ||
717 | /* | 775 | /* |
718 | * If we see that FP is active we assume we have one. | 776 | * If we see that FP is active we assume we have one. |
719 | * Otherwise we have a CRT display.User can override. | 777 | * Otherwise we have a CRT display. User can override. |
720 | */ | 778 | */ |
721 | static unsigned int __devinit get_displaytype(void) | 779 | static int __devinit is_flatpanel(struct tridentfb_par *par) |
722 | { | 780 | { |
723 | if (fp) | 781 | if (fp) |
724 | return DISPLAY_FP; | 782 | return 1; |
725 | if (crt || !chipcyber) | 783 | if (crt || !iscyber(par->chip_id)) |
726 | return DISPLAY_CRT; | 784 | return 0; |
727 | return (read3CE(FPConfig) & 0x10) ? DISPLAY_FP : DISPLAY_CRT; | 785 | return (read3CE(par, FPConfig) & 0x10) ? 1 : 0; |
728 | } | 786 | } |
729 | 787 | ||
730 | /* Try detecting the video memory size */ | 788 | /* Try detecting the video memory size */ |
731 | static unsigned int __devinit get_memsize(void) | 789 | static unsigned int __devinit get_memsize(struct tridentfb_par *par) |
732 | { | 790 | { |
733 | unsigned char tmp, tmp2; | 791 | unsigned char tmp, tmp2; |
734 | unsigned int k; | 792 | unsigned int k; |
@@ -737,12 +795,12 @@ static unsigned int __devinit get_memsize(void) | |||
737 | if (memsize) | 795 | if (memsize) |
738 | k = memsize * Kb; | 796 | k = memsize * Kb; |
739 | else | 797 | else |
740 | switch (chip_id) { | 798 | switch (par->chip_id) { |
741 | case CYBER9525DVD: | 799 | case CYBER9525DVD: |
742 | k = 2560 * Kb; | 800 | k = 2560 * Kb; |
743 | break; | 801 | break; |
744 | default: | 802 | default: |
745 | tmp = read3X4(SPR) & 0x0F; | 803 | tmp = read3X4(par, SPR) & 0x0F; |
746 | switch (tmp) { | 804 | switch (tmp) { |
747 | 805 | ||
748 | case 0x01: | 806 | case 0x01: |
@@ -774,7 +832,7 @@ static unsigned int __devinit get_memsize(void) | |||
774 | break; | 832 | break; |
775 | case 0x0E: /* XP */ | 833 | case 0x0E: /* XP */ |
776 | 834 | ||
777 | tmp2 = read3C4(0xC1); | 835 | tmp2 = vga_mm_rseq(par->io_virt, 0xC1); |
778 | switch (tmp2) { | 836 | switch (tmp2) { |
779 | case 0x00: | 837 | case 0x00: |
780 | k = 20 * Mb; | 838 | k = 20 * Mb; |
@@ -812,26 +870,67 @@ static unsigned int __devinit get_memsize(void) | |||
812 | static int tridentfb_check_var(struct fb_var_screeninfo *var, | 870 | static int tridentfb_check_var(struct fb_var_screeninfo *var, |
813 | struct fb_info *info) | 871 | struct fb_info *info) |
814 | { | 872 | { |
873 | struct tridentfb_par *par = info->par; | ||
815 | int bpp = var->bits_per_pixel; | 874 | int bpp = var->bits_per_pixel; |
875 | int line_length; | ||
876 | int ramdac = 230000; /* 230MHz for most 3D chips */ | ||
816 | debug("enter\n"); | 877 | debug("enter\n"); |
817 | 878 | ||
818 | /* check color depth */ | 879 | /* check color depth */ |
819 | if (bpp == 24) | 880 | if (bpp == 24) |
820 | bpp = var->bits_per_pixel = 32; | 881 | bpp = var->bits_per_pixel = 32; |
882 | if (bpp != 8 && bpp != 16 && bpp != 32) | ||
883 | return -EINVAL; | ||
884 | if (par->chip_id == TGUI9440 && bpp == 32) | ||
885 | return -EINVAL; | ||
821 | /* check whether resolution fits on panel and in memory */ | 886 | /* check whether resolution fits on panel and in memory */ |
822 | if (flatpanel && nativex && var->xres > nativex) | 887 | if (par->flatpanel && nativex && var->xres > nativex) |
888 | return -EINVAL; | ||
889 | /* various resolution checks */ | ||
890 | var->xres = (var->xres + 7) & ~0x7; | ||
891 | if (var->xres > var->xres_virtual) | ||
892 | var->xres_virtual = var->xres; | ||
893 | if (var->yres > var->yres_virtual) | ||
894 | var->yres_virtual = var->yres; | ||
895 | if (var->xres_virtual > 4095 || var->yres > 2048) | ||
823 | return -EINVAL; | 896 | return -EINVAL; |
824 | if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len) | 897 | /* prevent from position overflow for acceleration */ |
898 | if (var->yres_virtual > 0xffff) | ||
899 | return -EINVAL; | ||
900 | line_length = var->xres_virtual * bpp / 8; | ||
901 | |||
902 | if (!is3Dchip(par->chip_id) && | ||
903 | !(info->flags & FBINFO_HWACCEL_DISABLED)) { | ||
904 | /* acceleration requires line length to be power of 2 */ | ||
905 | if (line_length <= 512) | ||
906 | var->xres_virtual = 512 * 8 / bpp; | ||
907 | else if (line_length <= 1024) | ||
908 | var->xres_virtual = 1024 * 8 / bpp; | ||
909 | else if (line_length <= 2048) | ||
910 | var->xres_virtual = 2048 * 8 / bpp; | ||
911 | else if (line_length <= 4096) | ||
912 | var->xres_virtual = 4096 * 8 / bpp; | ||
913 | else if (line_length <= 8192) | ||
914 | var->xres_virtual = 8192 * 8 / bpp; | ||
915 | else | ||
916 | return -EINVAL; | ||
917 | |||
918 | line_length = var->xres_virtual * bpp / 8; | ||
919 | } | ||
920 | |||
921 | /* datasheet specifies how to set panning only up to 4 MB */ | ||
922 | if (line_length * (var->yres_virtual - var->yres) > (4 << 20)) | ||
923 | var->yres_virtual = ((4 << 20) / line_length) + var->yres; | ||
924 | |||
925 | if (line_length * var->yres_virtual > info->fix.smem_len) | ||
825 | return -EINVAL; | 926 | return -EINVAL; |
826 | 927 | ||
827 | switch (bpp) { | 928 | switch (bpp) { |
828 | case 8: | 929 | case 8: |
829 | var->red.offset = 0; | 930 | var->red.offset = 0; |
830 | var->green.offset = 0; | 931 | var->red.length = 8; |
831 | var->blue.offset = 0; | 932 | var->green = var->red; |
832 | var->red.length = 6; | 933 | var->blue = var->red; |
833 | var->green.length = 6; | ||
834 | var->blue.length = 6; | ||
835 | break; | 934 | break; |
836 | case 16: | 935 | case 16: |
837 | var->red.offset = 11; | 936 | var->red.offset = 11; |
@@ -852,6 +951,33 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var, | |||
852 | default: | 951 | default: |
853 | return -EINVAL; | 952 | return -EINVAL; |
854 | } | 953 | } |
954 | |||
955 | if (is_xp(par->chip_id)) | ||
956 | ramdac = 350000; | ||
957 | |||
958 | switch (par->chip_id) { | ||
959 | case TGUI9440: | ||
960 | ramdac = (bpp >= 16) ? 45000 : 90000; | ||
961 | break; | ||
962 | case CYBER9320: | ||
963 | case TGUI9660: | ||
964 | ramdac = 135000; | ||
965 | break; | ||
966 | case PROVIDIA9685: | ||
967 | case CYBER9388: | ||
968 | case CYBER9382: | ||
969 | case CYBER9385: | ||
970 | ramdac = 170000; | ||
971 | break; | ||
972 | } | ||
973 | |||
974 | /* The clock is doubled for 32 bpp */ | ||
975 | if (bpp == 32) | ||
976 | ramdac /= 2; | ||
977 | |||
978 | if (PICOS2KHZ(var->pixclock) > ramdac) | ||
979 | return -EINVAL; | ||
980 | |||
855 | debug("exit\n"); | 981 | debug("exit\n"); |
856 | 982 | ||
857 | return 0; | 983 | return 0; |
@@ -862,25 +988,31 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var, | |||
862 | static int tridentfb_pan_display(struct fb_var_screeninfo *var, | 988 | static int tridentfb_pan_display(struct fb_var_screeninfo *var, |
863 | struct fb_info *info) | 989 | struct fb_info *info) |
864 | { | 990 | { |
991 | struct tridentfb_par *par = info->par; | ||
865 | unsigned int offset; | 992 | unsigned int offset; |
866 | 993 | ||
867 | debug("enter\n"); | 994 | debug("enter\n"); |
868 | offset = (var->xoffset + (var->yoffset * var->xres)) | 995 | offset = (var->xoffset + (var->yoffset * var->xres_virtual)) |
869 | * var->bits_per_pixel / 32; | 996 | * var->bits_per_pixel / 32; |
870 | info->var.xoffset = var->xoffset; | 997 | set_screen_start(par, offset); |
871 | info->var.yoffset = var->yoffset; | ||
872 | set_screen_start(offset); | ||
873 | debug("exit\n"); | 998 | debug("exit\n"); |
874 | return 0; | 999 | return 0; |
875 | } | 1000 | } |
876 | 1001 | ||
877 | #define shadowmode_on() write3CE(CyberControl, read3CE(CyberControl) | 0x81) | 1002 | static inline void shadowmode_on(struct tridentfb_par *par) |
878 | #define shadowmode_off() write3CE(CyberControl, read3CE(CyberControl) & 0x7E) | 1003 | { |
1004 | write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81); | ||
1005 | } | ||
1006 | |||
1007 | static inline void shadowmode_off(struct tridentfb_par *par) | ||
1008 | { | ||
1009 | write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E); | ||
1010 | } | ||
879 | 1011 | ||
880 | /* Set the hardware to the requested video mode */ | 1012 | /* Set the hardware to the requested video mode */ |
881 | static int tridentfb_set_par(struct fb_info *info) | 1013 | static int tridentfb_set_par(struct fb_info *info) |
882 | { | 1014 | { |
883 | struct tridentfb_par *par = (struct tridentfb_par *)(info->par); | 1015 | struct tridentfb_par *par = info->par; |
884 | u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; | 1016 | u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; |
885 | u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; | 1017 | u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; |
886 | struct fb_var_screeninfo *var = &info->var; | 1018 | struct fb_var_screeninfo *var = &info->var; |
@@ -891,58 +1023,73 @@ static int tridentfb_set_par(struct fb_info *info) | |||
891 | debug("enter\n"); | 1023 | debug("enter\n"); |
892 | hdispend = var->xres / 8 - 1; | 1024 | hdispend = var->xres / 8 - 1; |
893 | hsyncstart = (var->xres + var->right_margin) / 8; | 1025 | hsyncstart = (var->xres + var->right_margin) / 8; |
894 | hsyncend = var->hsync_len / 8; | 1026 | hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8; |
895 | htotal = | 1027 | htotal = (var->xres + var->left_margin + var->right_margin + |
896 | (var->xres + var->left_margin + var->right_margin + | 1028 | var->hsync_len) / 8 - 5; |
897 | var->hsync_len) / 8 - 10; | ||
898 | hblankstart = hdispend + 1; | 1029 | hblankstart = hdispend + 1; |
899 | hblankend = htotal + 5; | 1030 | hblankend = htotal + 3; |
900 | 1031 | ||
901 | vdispend = var->yres - 1; | 1032 | vdispend = var->yres - 1; |
902 | vsyncstart = var->yres + var->lower_margin; | 1033 | vsyncstart = var->yres + var->lower_margin; |
903 | vsyncend = var->vsync_len; | 1034 | vsyncend = vsyncstart + var->vsync_len; |
904 | vtotal = var->upper_margin + vsyncstart + vsyncend - 2; | 1035 | vtotal = var->upper_margin + vsyncend - 2; |
905 | vblankstart = var->yres; | 1036 | vblankstart = vdispend + 1; |
906 | vblankend = vtotal + 2; | 1037 | vblankend = vtotal; |
1038 | |||
1039 | if (info->var.vmode & FB_VMODE_INTERLACED) { | ||
1040 | vtotal /= 2; | ||
1041 | vdispend /= 2; | ||
1042 | vsyncstart /= 2; | ||
1043 | vsyncend /= 2; | ||
1044 | vblankstart /= 2; | ||
1045 | vblankend /= 2; | ||
1046 | } | ||
907 | 1047 | ||
908 | crtc_unlock(); | 1048 | enable_mmio(par); |
909 | write3CE(CyberControl, 8); | 1049 | crtc_unlock(par); |
1050 | write3CE(par, CyberControl, 8); | ||
1051 | tmp = 0xEB; | ||
1052 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | ||
1053 | tmp &= ~0x40; | ||
1054 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | ||
1055 | tmp &= ~0x80; | ||
910 | 1056 | ||
911 | if (flatpanel && var->xres < nativex) { | 1057 | if (par->flatpanel && var->xres < nativex) { |
912 | /* | 1058 | /* |
913 | * on flat panels with native size larger | 1059 | * on flat panels with native size larger |
914 | * than requested resolution decide whether | 1060 | * than requested resolution decide whether |
915 | * we stretch or center | 1061 | * we stretch or center |
916 | */ | 1062 | */ |
917 | t_outb(0xEB, 0x3C2); | 1063 | t_outb(par, tmp | 0xC0, VGA_MIS_W); |
918 | 1064 | ||
919 | shadowmode_on(); | 1065 | shadowmode_on(par); |
920 | 1066 | ||
921 | if (center) | 1067 | if (center) |
922 | screen_center(); | 1068 | screen_center(par); |
923 | else if (stretch) | 1069 | else if (stretch) |
924 | screen_stretch(); | 1070 | screen_stretch(par); |
925 | 1071 | ||
926 | } else { | 1072 | } else { |
927 | t_outb(0x2B, 0x3C2); | 1073 | t_outb(par, tmp, VGA_MIS_W); |
928 | write3CE(CyberControl, 8); | 1074 | write3CE(par, CyberControl, 8); |
929 | } | 1075 | } |
930 | 1076 | ||
931 | /* vertical timing values */ | 1077 | /* vertical timing values */ |
932 | write3X4(CRTVTotal, vtotal & 0xFF); | 1078 | write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF); |
933 | write3X4(CRTVDispEnd, vdispend & 0xFF); | 1079 | write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF); |
934 | write3X4(CRTVSyncStart, vsyncstart & 0xFF); | 1080 | write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF); |
935 | write3X4(CRTVSyncEnd, (vsyncend & 0x0F)); | 1081 | write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F)); |
936 | write3X4(CRTVBlankStart, vblankstart & 0xFF); | 1082 | write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF); |
937 | write3X4(CRTVBlankEnd, 0 /* p->vblankend & 0xFF */ ); | 1083 | write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF); |
938 | 1084 | ||
939 | /* horizontal timing values */ | 1085 | /* horizontal timing values */ |
940 | write3X4(CRTHTotal, htotal & 0xFF); | 1086 | write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF); |
941 | write3X4(CRTHDispEnd, hdispend & 0xFF); | 1087 | write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF); |
942 | write3X4(CRTHSyncStart, hsyncstart & 0xFF); | 1088 | write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF); |
943 | write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2)); | 1089 | write3X4(par, VGA_CRTC_H_SYNC_END, |
944 | write3X4(CRTHBlankStart, hblankstart & 0xFF); | 1090 | (hsyncend & 0x1F) | ((hblankend & 0x20) << 2)); |
945 | write3X4(CRTHBlankEnd, 0 /* (p->hblankend & 0x1F) */ ); | 1091 | write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF); |
1092 | write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F); | ||
946 | 1093 | ||
947 | /* higher bits of vertical timing values */ | 1094 | /* higher bits of vertical timing values */ |
948 | tmp = 0x10; | 1095 | tmp = 0x10; |
@@ -954,39 +1101,43 @@ static int tridentfb_set_par(struct fb_info *info) | |||
954 | if (vtotal & 0x200) tmp |= 0x20; | 1101 | if (vtotal & 0x200) tmp |= 0x20; |
955 | if (vdispend & 0x200) tmp |= 0x40; | 1102 | if (vdispend & 0x200) tmp |= 0x40; |
956 | if (vsyncstart & 0x200) tmp |= 0x80; | 1103 | if (vsyncstart & 0x200) tmp |= 0x80; |
957 | write3X4(CRTOverflow, tmp); | 1104 | write3X4(par, VGA_CRTC_OVERFLOW, tmp); |
958 | 1105 | ||
959 | tmp = read3X4(CRTHiOrd) | 0x08; /* line compare bit 10 */ | 1106 | tmp = read3X4(par, CRTHiOrd) & 0x07; |
1107 | tmp |= 0x08; /* line compare bit 10 */ | ||
960 | if (vtotal & 0x400) tmp |= 0x80; | 1108 | if (vtotal & 0x400) tmp |= 0x80; |
961 | if (vblankstart & 0x400) tmp |= 0x40; | 1109 | if (vblankstart & 0x400) tmp |= 0x40; |
962 | if (vsyncstart & 0x400) tmp |= 0x20; | 1110 | if (vsyncstart & 0x400) tmp |= 0x20; |
963 | if (vdispend & 0x400) tmp |= 0x10; | 1111 | if (vdispend & 0x400) tmp |= 0x10; |
964 | write3X4(CRTHiOrd, tmp); | 1112 | write3X4(par, CRTHiOrd, tmp); |
965 | 1113 | ||
966 | tmp = 0; | 1114 | tmp = (htotal >> 8) & 0x01; |
967 | if (htotal & 0x800) tmp |= 0x800 >> 11; | 1115 | tmp |= (hdispend >> 7) & 0x02; |
968 | if (hblankstart & 0x800) tmp |= 0x800 >> 7; | 1116 | tmp |= (hsyncstart >> 5) & 0x08; |
969 | write3X4(HorizOverflow, tmp); | 1117 | tmp |= (hblankstart >> 4) & 0x10; |
1118 | write3X4(par, HorizOverflow, tmp); | ||
970 | 1119 | ||
971 | tmp = 0x40; | 1120 | tmp = 0x40; |
972 | if (vblankstart & 0x200) tmp |= 0x20; | 1121 | if (vblankstart & 0x200) tmp |= 0x20; |
973 | //FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */ | 1122 | //FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */ |
974 | write3X4(CRTMaxScanLine, tmp); | 1123 | write3X4(par, VGA_CRTC_MAX_SCAN, tmp); |
975 | 1124 | ||
976 | write3X4(CRTLineCompare, 0xFF); | 1125 | write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF); |
977 | write3X4(CRTPRowScan, 0); | 1126 | write3X4(par, VGA_CRTC_PRESET_ROW, 0); |
978 | write3X4(CRTModeControl, 0xC3); | 1127 | write3X4(par, VGA_CRTC_MODE, 0xC3); |
979 | 1128 | ||
980 | write3X4(LinearAddReg, 0x20); /* enable linear addressing */ | 1129 | write3X4(par, LinearAddReg, 0x20); /* enable linear addressing */ |
981 | 1130 | ||
982 | tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; | 1131 | tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; |
983 | write3X4(CRTCModuleTest, tmp); /* enable access extended memory */ | 1132 | /* enable access extended memory */ |
984 | 1133 | write3X4(par, CRTCModuleTest, tmp); | |
985 | write3X4(GraphEngReg, 0x80); /* enable GE for text acceleration */ | 1134 | tmp = read3CE(par, MiscIntContReg) & ~0x4; |
1135 | if (info->var.vmode & FB_VMODE_INTERLACED) | ||
1136 | tmp |= 0x4; | ||
1137 | write3CE(par, MiscIntContReg, tmp); | ||
986 | 1138 | ||
987 | #ifdef CONFIG_FB_TRIDENT_ACCEL | 1139 | /* enable GE for text acceleration */ |
988 | acc->init_accel(info->var.xres, bpp); | 1140 | write3X4(par, GraphEngReg, 0x80); |
989 | #endif | ||
990 | 1141 | ||
991 | switch (bpp) { | 1142 | switch (bpp) { |
992 | case 8: | 1143 | case 8: |
@@ -1003,57 +1154,59 @@ static int tridentfb_set_par(struct fb_info *info) | |||
1003 | break; | 1154 | break; |
1004 | } | 1155 | } |
1005 | 1156 | ||
1006 | write3X4(PixelBusReg, tmp); | 1157 | write3X4(par, PixelBusReg, tmp); |
1007 | 1158 | ||
1008 | tmp = 0x10; | 1159 | tmp = read3X4(par, DRAMControl); |
1009 | if (chipcyber) | 1160 | if (!is_oldprotect(par->chip_id)) |
1161 | tmp |= 0x10; | ||
1162 | if (iscyber(par->chip_id)) | ||
1010 | tmp |= 0x20; | 1163 | tmp |= 0x20; |
1011 | write3X4(DRAMControl, tmp); /* both IO, linear enable */ | 1164 | write3X4(par, DRAMControl, tmp); /* both IO, linear enable */ |
1012 | 1165 | ||
1013 | write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); | 1166 | write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40); |
1014 | write3X4(Performance, 0x92); | 1167 | if (!is_xp(par->chip_id)) |
1015 | write3X4(PCIReg, 0x07); /* MMIO & PCI read and write burst enable */ | 1168 | write3X4(par, Performance, read3X4(par, Performance) | 0x10); |
1169 | /* MMIO & PCI read and write burst enable */ | ||
1170 | if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975) | ||
1171 | write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06); | ||
1172 | |||
1173 | vga_mm_wseq(par->io_virt, 0, 3); | ||
1174 | vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */ | ||
1175 | /* enable 4 maps because needed in chain4 mode */ | ||
1176 | vga_mm_wseq(par->io_virt, 2, 0x0F); | ||
1177 | vga_mm_wseq(par->io_virt, 3, 0); | ||
1178 | vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */ | ||
1016 | 1179 | ||
1017 | /* convert from picoseconds to kHz */ | 1180 | /* convert from picoseconds to kHz */ |
1018 | vclk = PICOS2KHZ(info->var.pixclock); | 1181 | vclk = PICOS2KHZ(info->var.pixclock); |
1019 | if (bpp == 32) | 1182 | |
1183 | /* divide clock by 2 if 32bpp chain4 mode display and CPU path */ | ||
1184 | tmp = read3CE(par, MiscExtFunc) & 0xF0; | ||
1185 | if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) { | ||
1186 | tmp |= 8; | ||
1020 | vclk *= 2; | 1187 | vclk *= 2; |
1021 | set_vclk(vclk); | ||
1022 | |||
1023 | write3C4(0, 3); | ||
1024 | write3C4(1, 1); /* set char clock 8 dots wide */ | ||
1025 | write3C4(2, 0x0F); /* enable 4 maps because needed in chain4 mode */ | ||
1026 | write3C4(3, 0); | ||
1027 | write3C4(4, 0x0E); /* memory mode enable bitmaps ?? */ | ||
1028 | |||
1029 | write3CE(MiscExtFunc, (bpp == 32) ? 0x1A : 0x12); /* divide clock by 2 if 32bpp */ | ||
1030 | /* chain4 mode display and CPU path */ | ||
1031 | write3CE(0x5, 0x40); /* no CGA compat, allow 256 col */ | ||
1032 | write3CE(0x6, 0x05); /* graphics mode */ | ||
1033 | write3CE(0x7, 0x0F); /* planes? */ | ||
1034 | |||
1035 | if (chip_id == CYBERBLADEXPAi1) { | ||
1036 | /* This fixes snow-effect in 32 bpp */ | ||
1037 | write3X4(CRTHSyncStart, 0x84); | ||
1038 | } | 1188 | } |
1189 | set_vclk(par, vclk); | ||
1190 | write3CE(par, MiscExtFunc, tmp | 0x12); | ||
1191 | write3CE(par, 0x5, 0x40); /* no CGA compat, allow 256 col */ | ||
1192 | write3CE(par, 0x6, 0x05); /* graphics mode */ | ||
1193 | write3CE(par, 0x7, 0x0F); /* planes? */ | ||
1039 | 1194 | ||
1040 | writeAttr(0x10, 0x41); /* graphics mode and support 256 color modes */ | 1195 | /* graphics mode and support 256 color modes */ |
1041 | writeAttr(0x12, 0x0F); /* planes */ | 1196 | writeAttr(par, 0x10, 0x41); |
1042 | writeAttr(0x13, 0); /* horizontal pel panning */ | 1197 | writeAttr(par, 0x12, 0x0F); /* planes */ |
1198 | writeAttr(par, 0x13, 0); /* horizontal pel panning */ | ||
1043 | 1199 | ||
1044 | /* colors */ | 1200 | /* colors */ |
1045 | for (tmp = 0; tmp < 0x10; tmp++) | 1201 | for (tmp = 0; tmp < 0x10; tmp++) |
1046 | writeAttr(tmp, tmp); | 1202 | writeAttr(par, tmp, tmp); |
1047 | readb(par->io_virt + CRT + 0x0A); /* flip-flop to index */ | 1203 | fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */ |
1048 | t_outb(0x20, 0x3C0); /* enable attr */ | 1204 | t_outb(par, 0x20, VGA_ATT_W); /* enable attr */ |
1049 | 1205 | ||
1050 | switch (bpp) { | 1206 | switch (bpp) { |
1051 | case 8: | 1207 | case 8: |
1052 | tmp = 0; | 1208 | tmp = 0; |
1053 | break; | 1209 | break; |
1054 | case 15: | ||
1055 | tmp = 0x10; | ||
1056 | break; | ||
1057 | case 16: | 1210 | case 16: |
1058 | tmp = 0x30; | 1211 | tmp = 0x30; |
1059 | break; | 1212 | break; |
@@ -1063,19 +1216,23 @@ static int tridentfb_set_par(struct fb_info *info) | |||
1063 | break; | 1216 | break; |
1064 | } | 1217 | } |
1065 | 1218 | ||
1066 | t_inb(0x3C8); | 1219 | t_inb(par, VGA_PEL_IW); |
1067 | t_inb(0x3C6); | 1220 | t_inb(par, VGA_PEL_MSK); |
1068 | t_inb(0x3C6); | 1221 | t_inb(par, VGA_PEL_MSK); |
1069 | t_inb(0x3C6); | 1222 | t_inb(par, VGA_PEL_MSK); |
1070 | t_inb(0x3C6); | 1223 | t_inb(par, VGA_PEL_MSK); |
1071 | t_outb(tmp, 0x3C6); | 1224 | t_outb(par, tmp, VGA_PEL_MSK); |
1072 | t_inb(0x3C8); | 1225 | t_inb(par, VGA_PEL_IW); |
1073 | 1226 | ||
1074 | if (flatpanel) | 1227 | if (par->flatpanel) |
1075 | set_number_of_lines(info->var.yres); | 1228 | set_number_of_lines(par, info->var.yres); |
1076 | set_lwidth(info->var.xres * bpp / (4 * 16)); | 1229 | info->fix.line_length = info->var.xres_virtual * bpp / 8; |
1230 | set_lwidth(par, info->fix.line_length / 8); | ||
1231 | |||
1232 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) | ||
1233 | par->init_accel(par, info->var.xres_virtual, bpp); | ||
1234 | |||
1077 | info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 1235 | info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
1078 | info->fix.line_length = info->var.xres * (bpp >> 3); | ||
1079 | info->cmap.len = (bpp == 8) ? 256 : 16; | 1236 | info->cmap.len = (bpp == 8) ? 256 : 16; |
1080 | debug("exit\n"); | 1237 | debug("exit\n"); |
1081 | return 0; | 1238 | return 0; |
@@ -1087,17 +1244,18 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
1087 | struct fb_info *info) | 1244 | struct fb_info *info) |
1088 | { | 1245 | { |
1089 | int bpp = info->var.bits_per_pixel; | 1246 | int bpp = info->var.bits_per_pixel; |
1247 | struct tridentfb_par *par = info->par; | ||
1090 | 1248 | ||
1091 | if (regno >= info->cmap.len) | 1249 | if (regno >= info->cmap.len) |
1092 | return 1; | 1250 | return 1; |
1093 | 1251 | ||
1094 | if (bpp == 8) { | 1252 | if (bpp == 8) { |
1095 | t_outb(0xFF, 0x3C6); | 1253 | t_outb(par, 0xFF, VGA_PEL_MSK); |
1096 | t_outb(regno, 0x3C8); | 1254 | t_outb(par, regno, VGA_PEL_IW); |
1097 | 1255 | ||
1098 | t_outb(red >> 10, 0x3C9); | 1256 | t_outb(par, red >> 10, VGA_PEL_D); |
1099 | t_outb(green >> 10, 0x3C9); | 1257 | t_outb(par, green >> 10, VGA_PEL_D); |
1100 | t_outb(blue >> 10, 0x3C9); | 1258 | t_outb(par, blue >> 10, VGA_PEL_D); |
1101 | 1259 | ||
1102 | } else if (regno < 16) { | 1260 | } else if (regno < 16) { |
1103 | if (bpp == 16) { /* RGB 565 */ | 1261 | if (bpp == 16) { /* RGB 565 */ |
@@ -1108,28 +1266,28 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
1108 | col |= col << 16; | 1266 | col |= col << 16; |
1109 | ((u32 *)(info->pseudo_palette))[regno] = col; | 1267 | ((u32 *)(info->pseudo_palette))[regno] = col; |
1110 | } else if (bpp == 32) /* ARGB 8888 */ | 1268 | } else if (bpp == 32) /* ARGB 8888 */ |
1111 | ((u32*)info->pseudo_palette)[regno] = | 1269 | ((u32 *)info->pseudo_palette)[regno] = |
1112 | ((transp & 0xFF00) << 16) | | 1270 | ((transp & 0xFF00) << 16) | |
1113 | ((red & 0xFF00) << 8) | | 1271 | ((red & 0xFF00) << 8) | |
1114 | ((green & 0xFF00)) | | 1272 | ((green & 0xFF00)) | |
1115 | ((blue & 0xFF00) >> 8); | 1273 | ((blue & 0xFF00) >> 8); |
1116 | } | 1274 | } |
1117 | 1275 | ||
1118 | /* debug("exit\n"); */ | ||
1119 | return 0; | 1276 | return 0; |
1120 | } | 1277 | } |
1121 | 1278 | ||
1122 | /* Try blanking the screen.For flat panels it does nothing */ | 1279 | /* Try blanking the screen. For flat panels it does nothing */ |
1123 | static int tridentfb_blank(int blank_mode, struct fb_info *info) | 1280 | static int tridentfb_blank(int blank_mode, struct fb_info *info) |
1124 | { | 1281 | { |
1125 | unsigned char PMCont, DPMSCont; | 1282 | unsigned char PMCont, DPMSCont; |
1283 | struct tridentfb_par *par = info->par; | ||
1126 | 1284 | ||
1127 | debug("enter\n"); | 1285 | debug("enter\n"); |
1128 | if (flatpanel) | 1286 | if (par->flatpanel) |
1129 | return 0; | 1287 | return 0; |
1130 | t_outb(0x04, 0x83C8); /* Read DPMS Control */ | 1288 | t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */ |
1131 | PMCont = t_inb(0x83C6) & 0xFC; | 1289 | PMCont = t_inb(par, 0x83C6) & 0xFC; |
1132 | DPMSCont = read3CE(PowerStatus) & 0xFC; | 1290 | DPMSCont = read3CE(par, PowerStatus) & 0xFC; |
1133 | switch (blank_mode) { | 1291 | switch (blank_mode) { |
1134 | case FB_BLANK_UNBLANK: | 1292 | case FB_BLANK_UNBLANK: |
1135 | /* Screen: On, HSync: On, VSync: On */ | 1293 | /* Screen: On, HSync: On, VSync: On */ |
@@ -1155,9 +1313,9 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info) | |||
1155 | break; | 1313 | break; |
1156 | } | 1314 | } |
1157 | 1315 | ||
1158 | write3CE(PowerStatus, DPMSCont); | 1316 | write3CE(par, PowerStatus, DPMSCont); |
1159 | t_outb(4, 0x83C8); | 1317 | t_outb(par, 4, 0x83C8); |
1160 | t_outb(PMCont, 0x83C6); | 1318 | t_outb(par, PMCont, 0x83C6); |
1161 | 1319 | ||
1162 | debug("exit\n"); | 1320 | debug("exit\n"); |
1163 | 1321 | ||
@@ -1174,33 +1332,46 @@ static struct fb_ops tridentfb_ops = { | |||
1174 | .fb_set_par = tridentfb_set_par, | 1332 | .fb_set_par = tridentfb_set_par, |
1175 | .fb_fillrect = tridentfb_fillrect, | 1333 | .fb_fillrect = tridentfb_fillrect, |
1176 | .fb_copyarea = tridentfb_copyarea, | 1334 | .fb_copyarea = tridentfb_copyarea, |
1177 | .fb_imageblit = cfb_imageblit, | 1335 | .fb_imageblit = tridentfb_imageblit, |
1336 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
1337 | .fb_sync = tridentfb_sync, | ||
1338 | #endif | ||
1178 | }; | 1339 | }; |
1179 | 1340 | ||
1180 | static int __devinit trident_pci_probe(struct pci_dev * dev, | 1341 | static int __devinit trident_pci_probe(struct pci_dev *dev, |
1181 | const struct pci_device_id * id) | 1342 | const struct pci_device_id *id) |
1182 | { | 1343 | { |
1183 | int err; | 1344 | int err; |
1184 | unsigned char revision; | 1345 | unsigned char revision; |
1346 | struct fb_info *info; | ||
1347 | struct tridentfb_par *default_par; | ||
1348 | int chip3D; | ||
1349 | int chip_id; | ||
1185 | 1350 | ||
1186 | err = pci_enable_device(dev); | 1351 | err = pci_enable_device(dev); |
1187 | if (err) | 1352 | if (err) |
1188 | return err; | 1353 | return err; |
1189 | 1354 | ||
1190 | chip_id = id->device; | 1355 | info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev); |
1356 | if (!info) | ||
1357 | return -ENOMEM; | ||
1358 | default_par = info->par; | ||
1191 | 1359 | ||
1192 | if (chip_id == CYBERBLADEi1) | 1360 | chip_id = id->device; |
1193 | output("*** Please do use cyblafb, Cyberblade/i1 support " | ||
1194 | "will soon be removed from tridentfb!\n"); | ||
1195 | 1361 | ||
1362 | #ifndef CONFIG_FB_TRIDENT_ACCEL | ||
1363 | noaccel = 1; | ||
1364 | #endif | ||
1196 | 1365 | ||
1197 | /* If PCI id is 0x9660 then further detect chip type */ | 1366 | /* If PCI id is 0x9660 then further detect chip type */ |
1198 | 1367 | ||
1199 | if (chip_id == TGUI9660) { | 1368 | if (chip_id == TGUI9660) { |
1200 | outb(RevisionID, 0x3C4); | 1369 | revision = vga_io_rseq(RevisionID); |
1201 | revision = inb(0x3C5); | ||
1202 | 1370 | ||
1203 | switch (revision) { | 1371 | switch (revision) { |
1372 | case 0x21: | ||
1373 | chip_id = PROVIDIA9685; | ||
1374 | break; | ||
1204 | case 0x22: | 1375 | case 0x22: |
1205 | case 0x23: | 1376 | case 0x23: |
1206 | chip_id = CYBER9397; | 1377 | chip_id = CYBER9397; |
@@ -1229,123 +1400,170 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, | |||
1229 | } | 1400 | } |
1230 | 1401 | ||
1231 | chip3D = is3Dchip(chip_id); | 1402 | chip3D = is3Dchip(chip_id); |
1232 | chipcyber = iscyber(chip_id); | ||
1233 | 1403 | ||
1234 | if (is_xp(chip_id)) { | 1404 | if (is_xp(chip_id)) { |
1235 | acc = &accel_xp; | 1405 | default_par->init_accel = xp_init_accel; |
1406 | default_par->wait_engine = xp_wait_engine; | ||
1407 | default_par->fill_rect = xp_fill_rect; | ||
1408 | default_par->copy_rect = xp_copy_rect; | ||
1409 | tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP; | ||
1236 | } else if (is_blade(chip_id)) { | 1410 | } else if (is_blade(chip_id)) { |
1237 | acc = &accel_blade; | 1411 | default_par->init_accel = blade_init_accel; |
1238 | } else { | 1412 | default_par->wait_engine = blade_wait_engine; |
1239 | acc = &accel_image; | 1413 | default_par->fill_rect = blade_fill_rect; |
1414 | default_par->copy_rect = blade_copy_rect; | ||
1415 | default_par->image_blit = blade_image_blit; | ||
1416 | tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D; | ||
1417 | } else if (chip3D) { /* 3DImage family left */ | ||
1418 | default_par->init_accel = image_init_accel; | ||
1419 | default_par->wait_engine = image_wait_engine; | ||
1420 | default_par->fill_rect = image_fill_rect; | ||
1421 | default_par->copy_rect = image_copy_rect; | ||
1422 | tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE; | ||
1423 | } else { /* TGUI 9440/96XX family */ | ||
1424 | default_par->init_accel = tgui_init_accel; | ||
1425 | default_par->wait_engine = xp_wait_engine; | ||
1426 | default_par->fill_rect = tgui_fill_rect; | ||
1427 | default_par->copy_rect = tgui_copy_rect; | ||
1428 | tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI; | ||
1240 | } | 1429 | } |
1241 | 1430 | ||
1242 | /* acceleration is on by default for 3D chips */ | 1431 | default_par->chip_id = chip_id; |
1243 | defaultaccel = chip3D && !noaccel; | ||
1244 | |||
1245 | fb_info.par = &default_par; | ||
1246 | 1432 | ||
1247 | /* setup MMIO region */ | 1433 | /* setup MMIO region */ |
1248 | tridentfb_fix.mmio_start = pci_resource_start(dev, 1); | 1434 | tridentfb_fix.mmio_start = pci_resource_start(dev, 1); |
1249 | tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000; | 1435 | tridentfb_fix.mmio_len = pci_resource_len(dev, 1); |
1250 | 1436 | ||
1251 | if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) { | 1437 | if (!request_mem_region(tridentfb_fix.mmio_start, |
1438 | tridentfb_fix.mmio_len, "tridentfb")) { | ||
1252 | debug("request_region failed!\n"); | 1439 | debug("request_region failed!\n"); |
1440 | framebuffer_release(info); | ||
1253 | return -1; | 1441 | return -1; |
1254 | } | 1442 | } |
1255 | 1443 | ||
1256 | default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); | 1444 | default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start, |
1445 | tridentfb_fix.mmio_len); | ||
1257 | 1446 | ||
1258 | if (!default_par.io_virt) { | 1447 | if (!default_par->io_virt) { |
1259 | debug("ioremap failed\n"); | 1448 | debug("ioremap failed\n"); |
1260 | err = -1; | 1449 | err = -1; |
1261 | goto out_unmap1; | 1450 | goto out_unmap1; |
1262 | } | 1451 | } |
1263 | 1452 | ||
1264 | enable_mmio(); | 1453 | enable_mmio(default_par); |
1265 | 1454 | ||
1266 | /* setup framebuffer memory */ | 1455 | /* setup framebuffer memory */ |
1267 | tridentfb_fix.smem_start = pci_resource_start(dev, 0); | 1456 | tridentfb_fix.smem_start = pci_resource_start(dev, 0); |
1268 | tridentfb_fix.smem_len = get_memsize(); | 1457 | tridentfb_fix.smem_len = get_memsize(default_par); |
1269 | 1458 | ||
1270 | if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { | 1459 | if (!request_mem_region(tridentfb_fix.smem_start, |
1460 | tridentfb_fix.smem_len, "tridentfb")) { | ||
1271 | debug("request_mem_region failed!\n"); | 1461 | debug("request_mem_region failed!\n"); |
1272 | disable_mmio(); | 1462 | disable_mmio(info->par); |
1273 | err = -1; | 1463 | err = -1; |
1274 | goto out_unmap1; | 1464 | goto out_unmap1; |
1275 | } | 1465 | } |
1276 | 1466 | ||
1277 | fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start, | 1467 | info->screen_base = ioremap_nocache(tridentfb_fix.smem_start, |
1278 | tridentfb_fix.smem_len); | 1468 | tridentfb_fix.smem_len); |
1279 | 1469 | ||
1280 | if (!fb_info.screen_base) { | 1470 | if (!info->screen_base) { |
1281 | debug("ioremap failed\n"); | 1471 | debug("ioremap failed\n"); |
1282 | err = -1; | 1472 | err = -1; |
1283 | goto out_unmap2; | 1473 | goto out_unmap2; |
1284 | } | 1474 | } |
1285 | 1475 | ||
1286 | output("%s board found\n", pci_name(dev)); | 1476 | default_par->flatpanel = is_flatpanel(default_par); |
1287 | displaytype = get_displaytype(); | ||
1288 | 1477 | ||
1289 | if (flatpanel) | 1478 | if (default_par->flatpanel) |
1290 | nativex = get_nativex(); | 1479 | nativex = get_nativex(default_par); |
1291 | 1480 | ||
1292 | fb_info.fix = tridentfb_fix; | 1481 | info->fix = tridentfb_fix; |
1293 | fb_info.fbops = &tridentfb_ops; | 1482 | info->fbops = &tridentfb_ops; |
1483 | info->pseudo_palette = default_par->pseudo_pal; | ||
1294 | 1484 | ||
1485 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | ||
1486 | if (!noaccel && default_par->init_accel) { | ||
1487 | info->flags &= ~FBINFO_HWACCEL_DISABLED; | ||
1488 | info->flags |= FBINFO_HWACCEL_COPYAREA; | ||
1489 | info->flags |= FBINFO_HWACCEL_FILLRECT; | ||
1490 | } else | ||
1491 | info->flags |= FBINFO_HWACCEL_DISABLED; | ||
1295 | 1492 | ||
1296 | fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 1493 | info->pixmap.addr = kmalloc(4096, GFP_KERNEL); |
1297 | #ifdef CONFIG_FB_TRIDENT_ACCEL | 1494 | if (!info->pixmap.addr) { |
1298 | fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; | 1495 | err = -ENOMEM; |
1299 | #endif | 1496 | goto out_unmap2; |
1300 | fb_info.pseudo_palette = pseudo_pal; | 1497 | } |
1498 | |||
1499 | info->pixmap.size = 4096; | ||
1500 | info->pixmap.buf_align = 4; | ||
1501 | info->pixmap.scan_align = 1; | ||
1502 | info->pixmap.access_align = 32; | ||
1503 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
1301 | 1504 | ||
1302 | if (!fb_find_mode(&default_var, &fb_info, | 1505 | if (default_par->image_blit) { |
1506 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT; | ||
1507 | info->pixmap.scan_align = 4; | ||
1508 | } | ||
1509 | |||
1510 | if (noaccel) { | ||
1511 | printk(KERN_DEBUG "disabling acceleration\n"); | ||
1512 | info->flags |= FBINFO_HWACCEL_DISABLED; | ||
1513 | info->pixmap.scan_align = 1; | ||
1514 | } | ||
1515 | |||
1516 | if (!fb_find_mode(&info->var, info, | ||
1303 | mode_option, NULL, 0, NULL, bpp)) { | 1517 | mode_option, NULL, 0, NULL, bpp)) { |
1304 | err = -EINVAL; | 1518 | err = -EINVAL; |
1305 | goto out_unmap2; | 1519 | goto out_unmap2; |
1306 | } | 1520 | } |
1307 | err = fb_alloc_cmap(&fb_info.cmap, 256, 0); | 1521 | err = fb_alloc_cmap(&info->cmap, 256, 0); |
1308 | if (err < 0) | 1522 | if (err < 0) |
1309 | goto out_unmap2; | 1523 | goto out_unmap2; |
1310 | 1524 | ||
1311 | if (defaultaccel && acc) | 1525 | info->var.activate |= FB_ACTIVATE_NOW; |
1312 | default_var.accel_flags |= FB_ACCELF_TEXT; | 1526 | info->device = &dev->dev; |
1313 | else | 1527 | if (register_framebuffer(info) < 0) { |
1314 | default_var.accel_flags &= ~FB_ACCELF_TEXT; | 1528 | printk(KERN_ERR "tridentfb: could not register framebuffer\n"); |
1315 | default_var.activate |= FB_ACTIVATE_NOW; | 1529 | fb_dealloc_cmap(&info->cmap); |
1316 | fb_info.var = default_var; | ||
1317 | fb_info.device = &dev->dev; | ||
1318 | if (register_framebuffer(&fb_info) < 0) { | ||
1319 | printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n"); | ||
1320 | fb_dealloc_cmap(&fb_info.cmap); | ||
1321 | err = -EINVAL; | 1530 | err = -EINVAL; |
1322 | goto out_unmap2; | 1531 | goto out_unmap2; |
1323 | } | 1532 | } |
1324 | output("fb%d: %s frame buffer device %dx%d-%dbpp\n", | 1533 | output("fb%d: %s frame buffer device %dx%d-%dbpp\n", |
1325 | fb_info.node, fb_info.fix.id, default_var.xres, | 1534 | info->node, info->fix.id, info->var.xres, |
1326 | default_var.yres, default_var.bits_per_pixel); | 1535 | info->var.yres, info->var.bits_per_pixel); |
1536 | |||
1537 | pci_set_drvdata(dev, info); | ||
1327 | return 0; | 1538 | return 0; |
1328 | 1539 | ||
1329 | out_unmap2: | 1540 | out_unmap2: |
1330 | if (fb_info.screen_base) | 1541 | kfree(info->pixmap.addr); |
1331 | iounmap(fb_info.screen_base); | 1542 | if (info->screen_base) |
1543 | iounmap(info->screen_base); | ||
1332 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); | 1544 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); |
1333 | disable_mmio(); | 1545 | disable_mmio(info->par); |
1334 | out_unmap1: | 1546 | out_unmap1: |
1335 | if (default_par.io_virt) | 1547 | if (default_par->io_virt) |
1336 | iounmap(default_par.io_virt); | 1548 | iounmap(default_par->io_virt); |
1337 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); | 1549 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); |
1550 | framebuffer_release(info); | ||
1338 | return err; | 1551 | return err; |
1339 | } | 1552 | } |
1340 | 1553 | ||
1341 | static void __devexit trident_pci_remove(struct pci_dev *dev) | 1554 | static void __devexit trident_pci_remove(struct pci_dev *dev) |
1342 | { | 1555 | { |
1343 | struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par; | 1556 | struct fb_info *info = pci_get_drvdata(dev); |
1344 | unregister_framebuffer(&fb_info); | 1557 | struct tridentfb_par *par = info->par; |
1558 | |||
1559 | unregister_framebuffer(info); | ||
1345 | iounmap(par->io_virt); | 1560 | iounmap(par->io_virt); |
1346 | iounmap(fb_info.screen_base); | 1561 | iounmap(info->screen_base); |
1347 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); | 1562 | release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); |
1348 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); | 1563 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); |
1564 | pci_set_drvdata(dev, NULL); | ||
1565 | kfree(info->pixmap.addr); | ||
1566 | framebuffer_release(info); | ||
1349 | } | 1567 | } |
1350 | 1568 | ||
1351 | /* List of boards that we are trying to support */ | 1569 | /* List of boards that we are trying to support */ |
@@ -1358,6 +1576,7 @@ static struct pci_device_id trident_devices[] = { | |||
1358 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1576 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1359 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1577 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1360 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1578 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1579 | {PCI_VENDOR_ID_TRIDENT, TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1361 | {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1580 | {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1362 | {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1581 | {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1363 | {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1582 | {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
@@ -1399,9 +1618,9 @@ static int __init tridentfb_setup(char *options) | |||
1399 | if (!strncmp(opt, "noaccel", 7)) | 1618 | if (!strncmp(opt, "noaccel", 7)) |
1400 | noaccel = 1; | 1619 | noaccel = 1; |
1401 | else if (!strncmp(opt, "fp", 2)) | 1620 | else if (!strncmp(opt, "fp", 2)) |
1402 | displaytype = DISPLAY_FP; | 1621 | fp = 1; |
1403 | else if (!strncmp(opt, "crt", 3)) | 1622 | else if (!strncmp(opt, "crt", 3)) |
1404 | displaytype = DISPLAY_CRT; | 1623 | fp = 0; |
1405 | else if (!strncmp(opt, "bpp=", 4)) | 1624 | else if (!strncmp(opt, "bpp=", 4)) |
1406 | bpp = simple_strtoul(opt + 4, NULL, 0); | 1625 | bpp = simple_strtoul(opt + 4, NULL, 0); |
1407 | else if (!strncmp(opt, "center", 6)) | 1626 | else if (!strncmp(opt, "center", 6)) |
@@ -1430,7 +1649,6 @@ static int __init tridentfb_init(void) | |||
1430 | return -ENODEV; | 1649 | return -ENODEV; |
1431 | tridentfb_setup(option); | 1650 | tridentfb_setup(option); |
1432 | #endif | 1651 | #endif |
1433 | output("Trident framebuffer %s initializing\n", VERSION); | ||
1434 | return pci_register_driver(&tridentfb_pci_driver); | 1652 | return pci_register_driver(&tridentfb_pci_driver); |
1435 | } | 1653 | } |
1436 | 1654 | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index cdbb56edb6cb..50744229c7a9 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -2054,8 +2054,8 @@ MODULE_PARM_DESC(maxhf, | |||
2054 | module_param(maxvf, ushort, 0); | 2054 | module_param(maxvf, ushort, 0); |
2055 | MODULE_PARM_DESC(maxvf, | 2055 | MODULE_PARM_DESC(maxvf, |
2056 | "Maximum vertical frequency [Hz], overrides EDID data"); | 2056 | "Maximum vertical frequency [Hz], overrides EDID data"); |
2057 | module_param_named(mode, mode_option, charp, 0); | 2057 | module_param(mode_option, charp, 0); |
2058 | MODULE_PARM_DESC(mode, | 2058 | MODULE_PARM_DESC(mode_option, |
2059 | "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\""); | 2059 | "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\""); |
2060 | module_param(vbemode, ushort, 0); | 2060 | module_param(vbemode, ushort, 0); |
2061 | MODULE_PARM_DESC(vbemode, | 2061 | MODULE_PARM_DESC(vbemode, |
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h index c4aba59d4809..7491abfcf1fc 100644 --- a/drivers/video/vermilion/vermilion.h +++ b/drivers/video/vermilion/vermilion.h | |||
@@ -30,7 +30,6 @@ | |||
30 | #define _VERMILION_H_ | 30 | #define _VERMILION_H_ |
31 | 31 | ||
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/version.h> | ||
34 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
35 | #include <asm/atomic.h> | 34 | #include <asm/atomic.h> |
36 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 072638a9528a..93fe08d6c78f 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
@@ -443,19 +443,29 @@ static int vfb_mmap(struct fb_info *info, | |||
443 | } | 443 | } |
444 | 444 | ||
445 | #ifndef MODULE | 445 | #ifndef MODULE |
446 | /* | ||
447 | * The virtual framebuffer driver is only enabled if explicitly | ||
448 | * requested by passing 'video=vfb:' (or any actual options). | ||
449 | */ | ||
446 | static int __init vfb_setup(char *options) | 450 | static int __init vfb_setup(char *options) |
447 | { | 451 | { |
448 | char *this_opt; | 452 | char *this_opt; |
449 | 453 | ||
454 | vfb_enable = 0; | ||
455 | |||
456 | if (!options) | ||
457 | return 1; | ||
458 | |||
450 | vfb_enable = 1; | 459 | vfb_enable = 1; |
451 | 460 | ||
452 | if (!options || !*options) | 461 | if (!*options) |
453 | return 1; | 462 | return 1; |
454 | 463 | ||
455 | while ((this_opt = strsep(&options, ",")) != NULL) { | 464 | while ((this_opt = strsep(&options, ",")) != NULL) { |
456 | if (!*this_opt) | 465 | if (!*this_opt) |
457 | continue; | 466 | continue; |
458 | if (!strncmp(this_opt, "disable", 7)) | 467 | /* Test disable for backwards compatibility */ |
468 | if (!strcmp(this_opt, "disable")) | ||
459 | vfb_enable = 0; | 469 | vfb_enable = 0; |
460 | } | 470 | } |
461 | return 1; | 471 | return 1; |
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 9b3c5923365e..e31bca8a0cb2 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -26,18 +26,6 @@ | |||
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <video/vga.h> | 27 | #include <video/vga.h> |
28 | 28 | ||
29 | #define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */ | ||
30 | #define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */ | ||
31 | |||
32 | #define SET_RESET_INDEX VGA_GFX_SR_VALUE /* Set/Reset Register index. */ | ||
33 | #define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE /* Enable Set/Reset Register index. */ | ||
34 | #define DATA_ROTATE_INDEX VGA_GFX_DATA_ROTATE /* Data Rotate Register index. */ | ||
35 | #define GRAPHICS_MODE_INDEX VGA_GFX_MODE /* Graphics Mode Register index. */ | ||
36 | #define BIT_MASK_INDEX VGA_GFX_BIT_MASK /* Bit Mask Register index. */ | ||
37 | |||
38 | #define dac_reg (VGA_PEL_IW) | ||
39 | #define dac_val (VGA_PEL_D) | ||
40 | |||
41 | #define VGA_FB_PHYS 0xA0000 | 29 | #define VGA_FB_PHYS 0xA0000 |
42 | #define VGA_FB_PHYS_LEN 65536 | 30 | #define VGA_FB_PHYS_LEN 65536 |
43 | 31 | ||
@@ -108,7 +96,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = { | |||
108 | .visual = FB_VISUAL_PSEUDOCOLOR, | 96 | .visual = FB_VISUAL_PSEUDOCOLOR, |
109 | .xpanstep = 8, | 97 | .xpanstep = 8, |
110 | .ypanstep = 1, | 98 | .ypanstep = 1, |
111 | .line_length = 640/8, | 99 | .line_length = 640 / 8, |
112 | .accel = FB_ACCEL_NONE | 100 | .accel = FB_ACCEL_NONE |
113 | }; | 101 | }; |
114 | 102 | ||
@@ -135,23 +123,22 @@ static inline int setmode(int mode) | |||
135 | { | 123 | { |
136 | int oldmode; | 124 | int oldmode; |
137 | 125 | ||
138 | vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX); | 126 | oldmode = vga_io_rgfx(VGA_GFX_MODE); |
139 | oldmode = vga_io_r(GRAPHICS_DATA_REG); | 127 | vga_io_w(VGA_GFX_D, mode); |
140 | vga_io_w(GRAPHICS_DATA_REG, mode); | ||
141 | return oldmode; | 128 | return oldmode; |
142 | } | 129 | } |
143 | 130 | ||
144 | /* Select the Bit Mask Register and return its value. */ | 131 | /* Select the Bit Mask Register and return its value. */ |
145 | static inline int selectmask(void) | 132 | static inline int selectmask(void) |
146 | { | 133 | { |
147 | return vga_io_rgfx(BIT_MASK_INDEX); | 134 | return vga_io_rgfx(VGA_GFX_BIT_MASK); |
148 | } | 135 | } |
149 | 136 | ||
150 | /* Set the value of the Bit Mask Register. It must already have been | 137 | /* Set the value of the Bit Mask Register. It must already have been |
151 | selected with selectmask(). */ | 138 | selected with selectmask(). */ |
152 | static inline void setmask(int mask) | 139 | static inline void setmask(int mask) |
153 | { | 140 | { |
154 | vga_io_w(GRAPHICS_DATA_REG, mask); | 141 | vga_io_w(VGA_GFX_D, mask); |
155 | } | 142 | } |
156 | 143 | ||
157 | /* Set the Data Rotate Register and return its old value. | 144 | /* Set the Data Rotate Register and return its old value. |
@@ -161,9 +148,8 @@ static inline int setop(int op) | |||
161 | { | 148 | { |
162 | int oldop; | 149 | int oldop; |
163 | 150 | ||
164 | vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX); | 151 | oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE); |
165 | oldop = vga_io_r(GRAPHICS_DATA_REG); | 152 | vga_io_w(VGA_GFX_D, op); |
166 | vga_io_w(GRAPHICS_DATA_REG, op); | ||
167 | return oldop; | 153 | return oldop; |
168 | } | 154 | } |
169 | 155 | ||
@@ -173,9 +159,8 @@ static inline int setsr(int sr) | |||
173 | { | 159 | { |
174 | int oldsr; | 160 | int oldsr; |
175 | 161 | ||
176 | vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX); | 162 | oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE); |
177 | oldsr = vga_io_r(GRAPHICS_DATA_REG); | 163 | vga_io_w(VGA_GFX_D, sr); |
178 | vga_io_w(GRAPHICS_DATA_REG, sr); | ||
179 | return oldsr; | 164 | return oldsr; |
180 | } | 165 | } |
181 | 166 | ||
@@ -184,22 +169,21 @@ static inline int setcolor(int color) | |||
184 | { | 169 | { |
185 | int oldcolor; | 170 | int oldcolor; |
186 | 171 | ||
187 | vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX); | 172 | oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE); |
188 | oldcolor = vga_io_r(GRAPHICS_DATA_REG); | 173 | vga_io_w(VGA_GFX_D, color); |
189 | vga_io_w(GRAPHICS_DATA_REG, color); | ||
190 | return oldcolor; | 174 | return oldcolor; |
191 | } | 175 | } |
192 | 176 | ||
193 | /* Return the value in the Graphics Address Register. */ | 177 | /* Return the value in the Graphics Address Register. */ |
194 | static inline int getindex(void) | 178 | static inline int getindex(void) |
195 | { | 179 | { |
196 | return vga_io_r(GRAPHICS_ADDR_REG); | 180 | return vga_io_r(VGA_GFX_I); |
197 | } | 181 | } |
198 | 182 | ||
199 | /* Set the value in the Graphics Address Register. */ | 183 | /* Set the value in the Graphics Address Register. */ |
200 | static inline void setindex(int index) | 184 | static inline void setindex(int index) |
201 | { | 185 | { |
202 | vga_io_w(GRAPHICS_ADDR_REG, index); | 186 | vga_io_w(VGA_GFX_I, index); |
203 | } | 187 | } |
204 | 188 | ||
205 | static void vga16fb_pan_var(struct fb_info *info, | 189 | static void vga16fb_pan_var(struct fb_info *info, |
@@ -672,10 +656,10 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b | |||
672 | 656 | ||
673 | static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) | 657 | static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) |
674 | { | 658 | { |
675 | outb(regno, dac_reg); | 659 | outb(regno, VGA_PEL_IW); |
676 | outb(red >> 10, dac_val); | 660 | outb(red >> 10, VGA_PEL_D); |
677 | outb(green >> 10, dac_val); | 661 | outb(green >> 10, VGA_PEL_D); |
678 | outb(blue >> 10, dac_val); | 662 | outb(blue >> 10, VGA_PEL_D); |
679 | } | 663 | } |
680 | 664 | ||
681 | static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, | 665 | static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, |
@@ -719,28 +703,15 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var, | |||
719 | blanking code was originally by Huang shi chao, and modified by | 703 | blanking code was originally by Huang shi chao, and modified by |
720 | Christoph Rimek (chrimek@toppoint.de) and todd j. derr | 704 | Christoph Rimek (chrimek@toppoint.de) and todd j. derr |
721 | (tjd@barefoot.org) for Linux. */ | 705 | (tjd@barefoot.org) for Linux. */ |
722 | #define attrib_port VGA_ATC_IW | ||
723 | #define seq_port_reg VGA_SEQ_I | ||
724 | #define seq_port_val VGA_SEQ_D | ||
725 | #define gr_port_reg VGA_GFX_I | ||
726 | #define gr_port_val VGA_GFX_D | ||
727 | #define video_misc_rd VGA_MIS_R | ||
728 | #define video_misc_wr VGA_MIS_W | ||
729 | #define vga_video_port_reg VGA_CRT_IC | ||
730 | #define vga_video_port_val VGA_CRT_DC | ||
731 | 706 | ||
732 | static void vga_vesa_blank(struct vga16fb_par *par, int mode) | 707 | static void vga_vesa_blank(struct vga16fb_par *par, int mode) |
733 | { | 708 | { |
734 | unsigned char SeqCtrlIndex; | 709 | unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); |
735 | unsigned char CrtCtrlIndex; | 710 | unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); |
736 | 711 | ||
737 | //cli(); | ||
738 | SeqCtrlIndex = vga_io_r(seq_port_reg); | ||
739 | CrtCtrlIndex = vga_io_r(vga_video_port_reg); | ||
740 | |||
741 | /* save original values of VGA controller registers */ | 712 | /* save original values of VGA controller registers */ |
742 | if(!par->vesa_blanked) { | 713 | if(!par->vesa_blanked) { |
743 | par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd); | 714 | par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R); |
744 | //sti(); | 715 | //sti(); |
745 | 716 | ||
746 | par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ | 717 | par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ |
@@ -756,12 +727,11 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode) | |||
756 | 727 | ||
757 | /* assure that video is enabled */ | 728 | /* assure that video is enabled */ |
758 | /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ | 729 | /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ |
759 | //cli(); | ||
760 | vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); | 730 | vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); |
761 | 731 | ||
762 | /* test for vertical retrace in process.... */ | 732 | /* test for vertical retrace in process.... */ |
763 | if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) | 733 | if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) |
764 | vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef); | 734 | vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef); |
765 | 735 | ||
766 | /* | 736 | /* |
767 | * Set <End of vertical retrace> to minimum (0) and | 737 | * Set <End of vertical retrace> to minimum (0) and |
@@ -769,12 +739,10 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode) | |||
769 | * Result: turn off vertical sync (VSync) pulse. | 739 | * Result: turn off vertical sync (VSync) pulse. |
770 | */ | 740 | */ |
771 | if (mode & FB_BLANK_VSYNC_SUSPEND) { | 741 | if (mode & FB_BLANK_VSYNC_SUSPEND) { |
772 | outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ | 742 | vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff); |
773 | outb_p(0xff,vga_video_port_val); /* maximum value */ | 743 | vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40); |
774 | outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ | 744 | /* bits 9,10 of vert. retrace */ |
775 | outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */ | 745 | vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84); |
776 | outb_p(0x07,vga_video_port_reg); /* Overflow */ | ||
777 | outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */ | ||
778 | } | 746 | } |
779 | 747 | ||
780 | if (mode & FB_BLANK_HSYNC_SUSPEND) { | 748 | if (mode & FB_BLANK_HSYNC_SUSPEND) { |
@@ -783,29 +751,22 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode) | |||
783 | * <Start of horizontal Retrace> to maximum | 751 | * <Start of horizontal Retrace> to maximum |
784 | * Result: turn off horizontal sync (HSync) pulse. | 752 | * Result: turn off horizontal sync (HSync) pulse. |
785 | */ | 753 | */ |
786 | outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ | 754 | vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff); |
787 | outb_p(0xff,vga_video_port_val); /* maximum */ | 755 | vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00); |
788 | outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ | ||
789 | outb_p(0x00,vga_video_port_val); /* minimum (0) */ | ||
790 | } | 756 | } |
791 | 757 | ||
792 | /* restore both index registers */ | 758 | /* restore both index registers */ |
793 | outb_p(SeqCtrlIndex,seq_port_reg); | 759 | outb_p(SeqCtrlIndex, VGA_SEQ_I); |
794 | outb_p(CrtCtrlIndex,vga_video_port_reg); | 760 | outb_p(CrtCtrlIndex, VGA_CRT_IC); |
795 | //sti(); | ||
796 | } | 761 | } |
797 | 762 | ||
798 | static void vga_vesa_unblank(struct vga16fb_par *par) | 763 | static void vga_vesa_unblank(struct vga16fb_par *par) |
799 | { | 764 | { |
800 | unsigned char SeqCtrlIndex; | 765 | unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I); |
801 | unsigned char CrtCtrlIndex; | 766 | unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC); |
802 | 767 | ||
803 | //cli(); | ||
804 | SeqCtrlIndex = vga_io_r(seq_port_reg); | ||
805 | CrtCtrlIndex = vga_io_r(vga_video_port_reg); | ||
806 | |||
807 | /* restore original values of VGA controller registers */ | 768 | /* restore original values of VGA controller registers */ |
808 | vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO); | 769 | vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO); |
809 | 770 | ||
810 | /* HorizontalTotal */ | 771 | /* HorizontalTotal */ |
811 | vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); | 772 | vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); |
@@ -827,9 +788,8 @@ static void vga_vesa_unblank(struct vga16fb_par *par) | |||
827 | vga_io_wseq(0x01, par->vga_state.ClockingMode); | 788 | vga_io_wseq(0x01, par->vga_state.ClockingMode); |
828 | 789 | ||
829 | /* restore index/control registers */ | 790 | /* restore index/control registers */ |
830 | vga_io_w(seq_port_reg, SeqCtrlIndex); | 791 | vga_io_w(VGA_SEQ_I, SeqCtrlIndex); |
831 | vga_io_w(vga_video_port_reg, CrtCtrlIndex); | 792 | vga_io_w(VGA_CRT_IC, CrtCtrlIndex); |
832 | //sti(); | ||
833 | } | 793 | } |
834 | 794 | ||
835 | static void vga_pal_blank(void) | 795 | static void vga_pal_blank(void) |
@@ -837,10 +797,10 @@ static void vga_pal_blank(void) | |||
837 | int i; | 797 | int i; |
838 | 798 | ||
839 | for (i=0; i<16; i++) { | 799 | for (i=0; i<16; i++) { |
840 | outb_p (i, dac_reg) ; | 800 | outb_p(i, VGA_PEL_IW); |
841 | outb_p (0, dac_val) ; | 801 | outb_p(0, VGA_PEL_D); |
842 | outb_p (0, dac_val) ; | 802 | outb_p(0, VGA_PEL_D); |
843 | outb_p (0, dac_val) ; | 803 | outb_p(0, VGA_PEL_D); |
844 | } | 804 | } |
845 | } | 805 | } |
846 | 806 | ||
@@ -1087,12 +1047,15 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are | |||
1087 | width = x2 - dx; | 1047 | width = x2 - dx; |
1088 | height = y2 - dy; | 1048 | height = y2 - dy; |
1089 | 1049 | ||
1050 | if (sx + dx < old_dx || sy + dy < old_dy) | ||
1051 | return; | ||
1052 | |||
1090 | /* update sx1,sy1 */ | 1053 | /* update sx1,sy1 */ |
1091 | sx += (dx - old_dx); | 1054 | sx += (dx - old_dx); |
1092 | sy += (dy - old_dy); | 1055 | sy += (dy - old_dy); |
1093 | 1056 | ||
1094 | /* the source must be completely inside the virtual screen */ | 1057 | /* the source must be completely inside the virtual screen */ |
1095 | if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres) | 1058 | if (sx + width > vxres || sy + height > vyres) |
1096 | return; | 1059 | return; |
1097 | 1060 | ||
1098 | switch (info->fix.type) { | 1061 | switch (info->fix.type) { |
@@ -1482,6 +1445,7 @@ static void __exit vga16fb_exit(void) | |||
1482 | platform_driver_unregister(&vga16fb_driver); | 1445 | platform_driver_unregister(&vga16fb_driver); |
1483 | } | 1446 | } |
1484 | 1447 | ||
1448 | MODULE_DESCRIPTION("Legacy VGA framebuffer device driver"); | ||
1485 | MODULE_LICENSE("GPL"); | 1449 | MODULE_LICENSE("GPL"); |
1486 | module_init(vga16fb_init); | 1450 | module_init(vga16fb_init); |
1487 | module_exit(vga16fb_exit); | 1451 | module_exit(vga16fb_exit); |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index 536ab11623f0..3df17dc8c3d7 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * (http://davesdomain.org.uk/viafb/) | 12 | * (http://davesdomain.org.uk/viafb/) |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/version.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
@@ -677,13 +676,13 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
677 | 676 | ||
678 | rc = pci_enable_device(dev); | 677 | rc = pci_enable_device(dev); |
679 | if (rc < 0) { | 678 | if (rc < 0) { |
680 | dev_err(info->dev, "cannot enable PCI device\n"); | 679 | dev_err(info->device, "cannot enable PCI device\n"); |
681 | goto err_enable_device; | 680 | goto err_enable_device; |
682 | } | 681 | } |
683 | 682 | ||
684 | rc = pci_request_regions(dev, "vt8623fb"); | 683 | rc = pci_request_regions(dev, "vt8623fb"); |
685 | if (rc < 0) { | 684 | if (rc < 0) { |
686 | dev_err(info->dev, "cannot reserve framebuffer region\n"); | 685 | dev_err(info->device, "cannot reserve framebuffer region\n"); |
687 | goto err_request_regions; | 686 | goto err_request_regions; |
688 | } | 687 | } |
689 | 688 | ||
@@ -696,14 +695,14 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
696 | info->screen_base = pci_iomap(dev, 0, 0); | 695 | info->screen_base = pci_iomap(dev, 0, 0); |
697 | if (! info->screen_base) { | 696 | if (! info->screen_base) { |
698 | rc = -ENOMEM; | 697 | rc = -ENOMEM; |
699 | dev_err(info->dev, "iomap for framebuffer failed\n"); | 698 | dev_err(info->device, "iomap for framebuffer failed\n"); |
700 | goto err_iomap_1; | 699 | goto err_iomap_1; |
701 | } | 700 | } |
702 | 701 | ||
703 | par->mmio_base = pci_iomap(dev, 1, 0); | 702 | par->mmio_base = pci_iomap(dev, 1, 0); |
704 | if (! par->mmio_base) { | 703 | if (! par->mmio_base) { |
705 | rc = -ENOMEM; | 704 | rc = -ENOMEM; |
706 | dev_err(info->dev, "iomap for MMIO failed\n"); | 705 | dev_err(info->device, "iomap for MMIO failed\n"); |
707 | goto err_iomap_2; | 706 | goto err_iomap_2; |
708 | } | 707 | } |
709 | 708 | ||
@@ -714,7 +713,7 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
714 | if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) | 713 | if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) |
715 | info->screen_size = memsize1 << 20; | 714 | info->screen_size = memsize1 << 20; |
716 | else { | 715 | else { |
717 | dev_err(info->dev, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2); | 716 | dev_err(info->device, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2); |
718 | info->screen_size = 16 << 20; | 717 | info->screen_size = 16 << 20; |
719 | } | 718 | } |
720 | 719 | ||
@@ -731,19 +730,19 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi | |||
731 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 730 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); |
732 | if (! ((rc == 1) || (rc == 2))) { | 731 | if (! ((rc == 1) || (rc == 2))) { |
733 | rc = -EINVAL; | 732 | rc = -EINVAL; |
734 | dev_err(info->dev, "mode %s not found\n", mode_option); | 733 | dev_err(info->device, "mode %s not found\n", mode_option); |
735 | goto err_find_mode; | 734 | goto err_find_mode; |
736 | } | 735 | } |
737 | 736 | ||
738 | rc = fb_alloc_cmap(&info->cmap, 256, 0); | 737 | rc = fb_alloc_cmap(&info->cmap, 256, 0); |
739 | if (rc < 0) { | 738 | if (rc < 0) { |
740 | dev_err(info->dev, "cannot allocate colormap\n"); | 739 | dev_err(info->device, "cannot allocate colormap\n"); |
741 | goto err_alloc_cmap; | 740 | goto err_alloc_cmap; |
742 | } | 741 | } |
743 | 742 | ||
744 | rc = register_framebuffer(info); | 743 | rc = register_framebuffer(info); |
745 | if (rc < 0) { | 744 | if (rc < 0) { |
746 | dev_err(info->dev, "cannot register framebugger\n"); | 745 | dev_err(info->device, "cannot register framebugger\n"); |
747 | goto err_reg_fb; | 746 | goto err_reg_fb; |
748 | } | 747 | } |
749 | 748 | ||
@@ -817,7 +816,7 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state) | |||
817 | struct fb_info *info = pci_get_drvdata(dev); | 816 | struct fb_info *info = pci_get_drvdata(dev); |
818 | struct vt8623fb_info *par = info->par; | 817 | struct vt8623fb_info *par = info->par; |
819 | 818 | ||
820 | dev_info(info->dev, "suspend\n"); | 819 | dev_info(info->device, "suspend\n"); |
821 | 820 | ||
822 | acquire_console_sem(); | 821 | acquire_console_sem(); |
823 | mutex_lock(&(par->open_lock)); | 822 | mutex_lock(&(par->open_lock)); |
@@ -848,16 +847,13 @@ static int vt8623_pci_resume(struct pci_dev* dev) | |||
848 | struct fb_info *info = pci_get_drvdata(dev); | 847 | struct fb_info *info = pci_get_drvdata(dev); |
849 | struct vt8623fb_info *par = info->par; | 848 | struct vt8623fb_info *par = info->par; |
850 | 849 | ||
851 | dev_info(info->dev, "resume\n"); | 850 | dev_info(info->device, "resume\n"); |
852 | 851 | ||
853 | acquire_console_sem(); | 852 | acquire_console_sem(); |
854 | mutex_lock(&(par->open_lock)); | 853 | mutex_lock(&(par->open_lock)); |
855 | 854 | ||
856 | if (par->ref_count == 0) { | 855 | if (par->ref_count == 0) |
857 | mutex_unlock(&(par->open_lock)); | 856 | goto fail; |
858 | release_console_sem(); | ||
859 | return 0; | ||
860 | } | ||
861 | 857 | ||
862 | pci_set_power_state(dev, PCI_D0); | 858 | pci_set_power_state(dev, PCI_D0); |
863 | pci_restore_state(dev); | 859 | pci_restore_state(dev); |
@@ -870,8 +866,8 @@ static int vt8623_pci_resume(struct pci_dev* dev) | |||
870 | vt8623fb_set_par(info); | 866 | vt8623fb_set_par(info); |
871 | fb_set_suspend(info, 0); | 867 | fb_set_suspend(info, 0); |
872 | 868 | ||
873 | mutex_unlock(&(par->open_lock)); | ||
874 | fail: | 869 | fail: |
870 | mutex_unlock(&(par->open_lock)); | ||
875 | release_console_sem(); | 871 | release_console_sem(); |
876 | 872 | ||
877 | return 0; | 873 | return 0; |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 7b3a8423f485..5da3d2423cc0 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/version.h> | ||
28 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
29 | #include <linux/string.h> | 28 | #include <linux/string.h> |
30 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |