aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig121
-rw-r--r--drivers/video/aty/Makefile1
-rw-r--r--drivers/video/aty/aty128fb.c322
-rw-r--r--drivers/video/aty/atyfb.h1
-rw-r--r--drivers/video/aty/atyfb_base.c184
-rw-r--r--drivers/video/aty/radeon_backlight.c247
-rw-r--r--drivers/video/aty/radeon_base.c140
-rw-r--r--drivers/video/aty/radeonfb.h9
-rw-r--r--drivers/video/au1100fb.c21
-rw-r--r--drivers/video/chipsfb.c30
-rw-r--r--drivers/video/console/fbcon.c4
-rw-r--r--drivers/video/console/mdacon.c2
-rw-r--r--drivers/video/console/vgacon.c19
-rw-r--r--drivers/video/fbsysfs.c88
-rw-r--r--drivers/video/igafb.c3
-rw-r--r--drivers/video/intelfb/intelfb.h18
-rw-r--r--drivers/video/intelfb/intelfbdrv.c103
-rw-r--r--drivers/video/intelfb/intelfbhw.c518
-rw-r--r--drivers/video/intelfb/intelfbhw.h25
-rw-r--r--drivers/video/matrox/matroxfb_base.c52
-rw-r--r--drivers/video/maxinefb.c4
-rw-r--r--drivers/video/nvidia/Makefile3
-rw-r--r--drivers/video/nvidia/nv_backlight.c175
-rw-r--r--drivers/video/nvidia/nv_proto.h10
-rw-r--r--drivers/video/nvidia/nvidia.c95
-rw-r--r--drivers/video/riva/fbdev.c222
-rw-r--r--drivers/video/tridentfb.c6
-rw-r--r--drivers/video/vga16fb.c2
28 files changed, 1725 insertions, 700 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4587087d777a..168ede7902bd 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -86,6 +86,11 @@ config FB_FIRMWARE_EDID
86 combination with certain motherboards and monitors are known to 86 combination with certain motherboards and monitors are known to
87 suffer from this problem. 87 suffer from this problem.
88 88
89config FB_BACKLIGHT
90 bool
91 depends on FB
92 default n
93
89config FB_MODE_HELPERS 94config FB_MODE_HELPERS
90 bool "Enable Video Mode Handling Helpers" 95 bool "Enable Video Mode Handling Helpers"
91 depends on FB 96 depends on FB
@@ -167,6 +172,69 @@ config FB_ARMCLCD
167 here and read <file:Documentation/modules.txt>. The module 172 here and read <file:Documentation/modules.txt>. The module
168 will be called amba-clcd. 173 will be called amba-clcd.
169 174
175choice
176
177 depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X)
178 prompt "LCD Panel"
179 default FB_ARMCLCD_SHARP_LQ035Q7DB02
180
181config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
182 bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC"
183 help
184 This is an implementation of the Sharp LQ035Q7DB02, a 3.5"
185 color QVGA, HRTFT panel. The LogicPD device includes an
186 an integrated HRTFT controller IC.
187 The native resolution is 240x320.
188
189config FB_ARMCLCD_SHARP_LQ057Q3DC02
190 bool "LogicPD LCD 5.7\" QVGA"
191 help
192 This is an implementation of the Sharp LQ057Q3DC02, a 5.7"
193 color QVGA, TFT panel. The LogicPD device includes an
194 The native resolution is 320x240.
195
196config FB_ARMCLCD_SHARP_LQ64D343
197 bool "LogicPD LCD 6.4\" VGA"
198 help
199 This is an implementation of the Sharp LQ64D343, a 6.4"
200 color VGA, TFT panel. The LogicPD device includes an
201 The native resolution is 640x480.
202
203config FB_ARMCLCD_SHARP_LQ10D368
204 bool "LogicPD LCD 10.4\" VGA"
205 help
206 This is an implementation of the Sharp LQ10D368, a 10.4"
207 color VGA, TFT panel. The LogicPD device includes an
208 The native resolution is 640x480.
209
210
211config FB_ARMCLCD_SHARP_LQ121S1DG41
212 bool "LogicPD LCD 12.1\" SVGA"
213 help
214 This is an implementation of the Sharp LQ121S1DG41, a 12.1"
215 color SVGA, TFT panel. The LogicPD device includes an
216 The native resolution is 800x600.
217
218 This panel requires a clock rate may be an integer fraction
219 of the base LCDCLK frequency. The driver will select the
220 highest frequency available that is lower than the maximum
221 allowed. The panel may flicker if the clock rate is
222 slower than the recommended minimum.
223
224config FB_ARMCLCD_AUO_A070VW01_WIDE
225 bool "AU Optronics A070VW01 LCD 7.0\" WIDE"
226 help
227 This is an implementation of the AU Optronics, a 7.0"
228 WIDE Color. The native resolution is 234x480.
229
230config FB_ARMCLCD_HITACHI
231 bool "Hitachi Wide Screen 800x480"
232 help
233 This is an implementation of the Hitachi 800x480.
234
235endchoice
236
237
170config FB_ACORN 238config FB_ACORN
171 bool "Acorn VIDC support" 239 bool "Acorn VIDC support"
172 depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500) 240 depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500)
@@ -654,6 +722,16 @@ config FB_NVIDIA_I2C
654 independently validate video mode parameters, you should say Y 722 independently validate video mode parameters, you should say Y
655 here. 723 here.
656 724
725config FB_NVIDIA_BACKLIGHT
726 bool "Support for backlight control"
727 depends on FB_NVIDIA && PPC_PMAC
728 select FB_BACKLIGHT
729 select BACKLIGHT_LCD_SUPPORT
730 select BACKLIGHT_CLASS_DEVICE
731 default y
732 help
733 Say Y here if you want to control the backlight of your display.
734
657config FB_RIVA 735config FB_RIVA
658 tristate "nVidia Riva support" 736 tristate "nVidia Riva support"
659 depends on FB && PCI 737 depends on FB && PCI
@@ -692,6 +770,16 @@ config FB_RIVA_DEBUG
692 of debugging informations to provide to the maintainer when 770 of debugging informations to provide to the maintainer when
693 something goes wrong. 771 something goes wrong.
694 772
773config FB_RIVA_BACKLIGHT
774 bool "Support for backlight control"
775 depends on FB_RIVA && PPC_PMAC
776 select FB_BACKLIGHT
777 select BACKLIGHT_LCD_SUPPORT
778 select BACKLIGHT_CLASS_DEVICE
779 default y
780 help
781 Say Y here if you want to control the backlight of your display.
782
695config FB_I810 783config FB_I810
696 tristate "Intel 810/815 support (EXPERIMENTAL)" 784 tristate "Intel 810/815 support (EXPERIMENTAL)"
697 depends on FB && EXPERIMENTAL && PCI && X86_32 785 depends on FB && EXPERIMENTAL && PCI && X86_32
@@ -743,7 +831,7 @@ config FB_I810_I2C
743 831
744config FB_INTEL 832config FB_INTEL
745 tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" 833 tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
746 depends on FB && EXPERIMENTAL && PCI && X86_32 834 depends on FB && EXPERIMENTAL && PCI && X86
747 select AGP 835 select AGP
748 select AGP_INTEL 836 select AGP_INTEL
749 select FB_MODE_HELPERS 837 select FB_MODE_HELPERS
@@ -930,6 +1018,7 @@ config FB_RADEON
930 1018
931 There is a product page at 1019 There is a product page at
932 http://apps.ati.com/ATIcompare/ 1020 http://apps.ati.com/ATIcompare/
1021
933config FB_RADEON_I2C 1022config FB_RADEON_I2C
934 bool "DDC/I2C for ATI Radeon support" 1023 bool "DDC/I2C for ATI Radeon support"
935 depends on FB_RADEON 1024 depends on FB_RADEON
@@ -937,6 +1026,16 @@ config FB_RADEON_I2C
937 help 1026 help
938 Say Y here if you want DDC/I2C support for your Radeon board. 1027 Say Y here if you want DDC/I2C support for your Radeon board.
939 1028
1029config FB_RADEON_BACKLIGHT
1030 bool "Support for backlight control"
1031 depends on FB_RADEON && PPC_PMAC
1032 select FB_BACKLIGHT
1033 select BACKLIGHT_LCD_SUPPORT
1034 select BACKLIGHT_CLASS_DEVICE
1035 default y
1036 help
1037 Say Y here if you want to control the backlight of your display.
1038
940config FB_RADEON_DEBUG 1039config FB_RADEON_DEBUG
941 bool "Lots of debug output from Radeon driver" 1040 bool "Lots of debug output from Radeon driver"
942 depends on FB_RADEON 1041 depends on FB_RADEON
@@ -961,6 +1060,16 @@ config FB_ATY128
961 To compile this driver as a module, choose M here: the 1060 To compile this driver as a module, choose M here: the
962 module will be called aty128fb. 1061 module will be called aty128fb.
963 1062
1063config FB_ATY128_BACKLIGHT
1064 bool "Support for backlight control"
1065 depends on FB_ATY128 && PPC_PMAC
1066 select FB_BACKLIGHT
1067 select BACKLIGHT_LCD_SUPPORT
1068 select BACKLIGHT_CLASS_DEVICE
1069 default y
1070 help
1071 Say Y here if you want to control the backlight of your display.
1072
964config FB_ATY 1073config FB_ATY
965 tristate "ATI Mach64 display support" if PCI || ATARI 1074 tristate "ATI Mach64 display support" if PCI || ATARI
966 depends on FB && !SPARC32 1075 depends on FB && !SPARC32
@@ -1003,6 +1112,16 @@ config FB_ATY_GX
1003 is at 1112 is at
1004 <http://support.ati.com/products/pc/mach64/graphics_xpression.html>. 1113 <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
1005 1114
1115config FB_ATY_BACKLIGHT
1116 bool "Support for backlight control"
1117 depends on FB_ATY && PPC_PMAC
1118 select FB_BACKLIGHT
1119 select BACKLIGHT_LCD_SUPPORT
1120 select BACKLIGHT_CLASS_DEVICE
1121 default y
1122 help
1123 Say Y here if you want to control the backlight of your display.
1124
1006config FB_S3TRIO 1125config FB_S3TRIO
1007 bool "S3 Trio display support" 1126 bool "S3 Trio display support"
1008 depends on (FB = y) && PPC && BROKEN 1127 depends on (FB = y) && PPC && BROKEN
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
index 18521397a6e3..a6cc0e9ec790 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/aty/Makefile
@@ -10,5 +10,6 @@ atyfb-objs := $(atyfb-y)
10 10
11radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o 11radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o
12radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o 12radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o
13radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT) += radeon_backlight.o
13radeonfb-objs := $(radeonfb-y) 14radeonfb-objs := $(radeonfb-y)
14 15
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index f7bbff4ddc6a..db878fd55fb2 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -64,6 +64,7 @@
64#include <linux/pci.h> 64#include <linux/pci.h>
65#include <linux/ioport.h> 65#include <linux/ioport.h>
66#include <linux/console.h> 66#include <linux/console.h>
67#include <linux/backlight.h>
67#include <asm/io.h> 68#include <asm/io.h>
68 69
69#ifdef CONFIG_PPC_PMAC 70#ifdef CONFIG_PPC_PMAC
@@ -480,16 +481,6 @@ static struct fb_ops aty128fb_ops = {
480 .fb_imageblit = cfb_imageblit, 481 .fb_imageblit = cfb_imageblit,
481}; 482};
482 483
483#ifdef CONFIG_PMAC_BACKLIGHT
484static int aty128_set_backlight_enable(int on, int level, void* data);
485static int aty128_set_backlight_level(int level, void* data);
486
487static struct backlight_controller aty128_backlight_controller = {
488 aty128_set_backlight_enable,
489 aty128_set_backlight_level
490};
491#endif /* CONFIG_PMAC_BACKLIGHT */
492
493 /* 484 /*
494 * Functions to read from/write to the mmio registers 485 * Functions to read from/write to the mmio registers
495 * - endian conversions may possibly be avoided by 486 * - endian conversions may possibly be avoided by
@@ -1258,19 +1249,35 @@ static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
1258static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) 1249static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
1259{ 1250{
1260 u32 reg; 1251 u32 reg;
1252#ifdef CONFIG_FB_ATY128_BACKLIGHT
1253 struct fb_info *info = pci_get_drvdata(par->pdev);
1254#endif
1261 1255
1262 if (on) { 1256 if (on) {
1263 reg = aty_ld_le32(LVDS_GEN_CNTL); 1257 reg = aty_ld_le32(LVDS_GEN_CNTL);
1264 reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION; 1258 reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
1265 reg &= ~LVDS_DISPLAY_DIS; 1259 reg &= ~LVDS_DISPLAY_DIS;
1266 aty_st_le32(LVDS_GEN_CNTL, reg); 1260 aty_st_le32(LVDS_GEN_CNTL, reg);
1267#ifdef CONFIG_PMAC_BACKLIGHT 1261#ifdef CONFIG_FB_ATY128_BACKLIGHT
1268 aty128_set_backlight_enable(get_backlight_enable(), 1262 mutex_lock(&info->bl_mutex);
1269 get_backlight_level(), par); 1263 if (info->bl_dev) {
1264 down(&info->bl_dev->sem);
1265 info->bl_dev->props->update_status(info->bl_dev);
1266 up(&info->bl_dev->sem);
1267 }
1268 mutex_unlock(&info->bl_mutex);
1270#endif 1269#endif
1271 } else { 1270 } else {
1272#ifdef CONFIG_PMAC_BACKLIGHT 1271#ifdef CONFIG_FB_ATY128_BACKLIGHT
1273 aty128_set_backlight_enable(0, 0, par); 1272 mutex_lock(&info->bl_mutex);
1273 if (info->bl_dev) {
1274 down(&info->bl_dev->sem);
1275 info->bl_dev->props->brightness = 0;
1276 info->bl_dev->props->power = FB_BLANK_POWERDOWN;
1277 info->bl_dev->props->update_status(info->bl_dev);
1278 up(&info->bl_dev->sem);
1279 }
1280 mutex_unlock(&info->bl_mutex);
1274#endif 1281#endif
1275 reg = aty_ld_le32(LVDS_GEN_CNTL); 1282 reg = aty_ld_le32(LVDS_GEN_CNTL);
1276 reg |= LVDS_DISPLAY_DIS; 1283 reg |= LVDS_DISPLAY_DIS;
@@ -1691,6 +1698,184 @@ static int __init aty128fb_setup(char *options)
1691} 1698}
1692#endif /* MODULE */ 1699#endif /* MODULE */
1693 1700
1701/* Backlight */
1702#ifdef CONFIG_FB_ATY128_BACKLIGHT
1703#define MAX_LEVEL 0xFF
1704
1705static struct backlight_properties aty128_bl_data;
1706
1707static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
1708 int level)
1709{
1710 struct fb_info *info = pci_get_drvdata(par->pdev);
1711 int atylevel;
1712
1713 /* Get and convert the value */
1714 mutex_lock(&info->bl_mutex);
1715 atylevel = MAX_LEVEL -
1716 (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
1717 mutex_unlock(&info->bl_mutex);
1718
1719 if (atylevel < 0)
1720 atylevel = 0;
1721 else if (atylevel > MAX_LEVEL)
1722 atylevel = MAX_LEVEL;
1723
1724 return atylevel;
1725}
1726
1727/* We turn off the LCD completely instead of just dimming the backlight.
1728 * This provides greater power saving and the display is useless without
1729 * backlight anyway
1730 */
1731#define BACKLIGHT_LVDS_OFF
1732/* That one prevents proper CRT output with LCD off */
1733#undef BACKLIGHT_DAC_OFF
1734
1735static int aty128_bl_update_status(struct backlight_device *bd)
1736{
1737 struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
1738 unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
1739 int level;
1740
1741 if (bd->props->power != FB_BLANK_UNBLANK ||
1742 bd->props->fb_blank != FB_BLANK_UNBLANK ||
1743 !par->lcd_on)
1744 level = 0;
1745 else
1746 level = bd->props->brightness;
1747
1748 reg |= LVDS_BL_MOD_EN | LVDS_BLON;
1749 if (level > 0) {
1750 reg |= LVDS_DIGION;
1751 if (!(reg & LVDS_ON)) {
1752 reg &= ~LVDS_BLON;
1753 aty_st_le32(LVDS_GEN_CNTL, reg);
1754 aty_ld_le32(LVDS_GEN_CNTL);
1755 mdelay(10);
1756 reg |= LVDS_BLON;
1757 aty_st_le32(LVDS_GEN_CNTL, reg);
1758 }
1759 reg &= ~LVDS_BL_MOD_LEVEL_MASK;
1760 reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT);
1761#ifdef BACKLIGHT_LVDS_OFF
1762 reg |= LVDS_ON | LVDS_EN;
1763 reg &= ~LVDS_DISPLAY_DIS;
1764#endif
1765 aty_st_le32(LVDS_GEN_CNTL, reg);
1766#ifdef BACKLIGHT_DAC_OFF
1767 aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
1768#endif
1769 } else {
1770 reg &= ~LVDS_BL_MOD_LEVEL_MASK;
1771 reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT);
1772#ifdef BACKLIGHT_LVDS_OFF
1773 reg |= LVDS_DISPLAY_DIS;
1774 aty_st_le32(LVDS_GEN_CNTL, reg);
1775 aty_ld_le32(LVDS_GEN_CNTL);
1776 udelay(10);
1777 reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
1778#endif
1779 aty_st_le32(LVDS_GEN_CNTL, reg);
1780#ifdef BACKLIGHT_DAC_OFF
1781 aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
1782#endif
1783 }
1784
1785 return 0;
1786}
1787
1788static int aty128_bl_get_brightness(struct backlight_device *bd)
1789{
1790 return bd->props->brightness;
1791}
1792
1793static struct backlight_properties aty128_bl_data = {
1794 .owner = THIS_MODULE,
1795 .get_brightness = aty128_bl_get_brightness,
1796 .update_status = aty128_bl_update_status,
1797 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
1798};
1799
1800static void aty128_bl_init(struct aty128fb_par *par)
1801{
1802 struct fb_info *info = pci_get_drvdata(par->pdev);
1803 struct backlight_device *bd;
1804 char name[12];
1805
1806 /* Could be extended to Rage128Pro LVDS output too */
1807 if (par->chip_gen != rage_M3)
1808 return;
1809
1810#ifdef CONFIG_PMAC_BACKLIGHT
1811 if (!pmac_has_backlight_type("ati"))
1812 return;
1813#endif
1814
1815 snprintf(name, sizeof(name), "aty128bl%d", info->node);
1816
1817 bd = backlight_device_register(name, par, &aty128_bl_data);
1818 if (IS_ERR(bd)) {
1819 info->bl_dev = NULL;
1820 printk("aty128: Backlight registration failed\n");
1821 goto error;
1822 }
1823
1824 mutex_lock(&info->bl_mutex);
1825 info->bl_dev = bd;
1826 fb_bl_default_curve(info, 0,
1827 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
1828 219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
1829 mutex_unlock(&info->bl_mutex);
1830
1831 up(&bd->sem);
1832 bd->props->brightness = aty128_bl_data.max_brightness;
1833 bd->props->power = FB_BLANK_UNBLANK;
1834 bd->props->update_status(bd);
1835 down(&bd->sem);
1836
1837#ifdef CONFIG_PMAC_BACKLIGHT
1838 mutex_lock(&pmac_backlight_mutex);
1839 if (!pmac_backlight)
1840 pmac_backlight = bd;
1841 mutex_unlock(&pmac_backlight_mutex);
1842#endif
1843
1844 printk("aty128: Backlight initialized (%s)\n", name);
1845
1846 return;
1847
1848error:
1849 return;
1850}
1851
1852static void aty128_bl_exit(struct aty128fb_par *par)
1853{
1854 struct fb_info *info = pci_get_drvdata(par->pdev);
1855
1856#ifdef CONFIG_PMAC_BACKLIGHT
1857 mutex_lock(&pmac_backlight_mutex);
1858#endif
1859
1860 mutex_lock(&info->bl_mutex);
1861 if (info->bl_dev) {
1862#ifdef CONFIG_PMAC_BACKLIGHT
1863 if (pmac_backlight == info->bl_dev)
1864 pmac_backlight = NULL;
1865#endif
1866
1867 backlight_device_unregister(info->bl_dev);
1868 info->bl_dev = NULL;
1869
1870 printk("aty128: Backlight unloaded\n");
1871 }
1872 mutex_unlock(&info->bl_mutex);
1873
1874#ifdef CONFIG_PMAC_BACKLIGHT
1875 mutex_unlock(&pmac_backlight_mutex);
1876#endif
1877}
1878#endif /* CONFIG_FB_ATY128_BACKLIGHT */
1694 1879
1695/* 1880/*
1696 * Initialisation 1881 * Initialisation
@@ -1835,17 +2020,15 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *
1835 if (register_framebuffer(info) < 0) 2020 if (register_framebuffer(info) < 0)
1836 return 0; 2021 return 0;
1837 2022
1838#ifdef CONFIG_PMAC_BACKLIGHT
1839 /* Could be extended to Rage128Pro LVDS output too */
1840 if (par->chip_gen == rage_M3)
1841 register_backlight_controller(&aty128_backlight_controller, par, "ati");
1842#endif /* CONFIG_PMAC_BACKLIGHT */
1843
1844 par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); 2023 par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
1845 par->pdev = pdev; 2024 par->pdev = pdev;
1846 par->asleep = 0; 2025 par->asleep = 0;
1847 par->lock_blank = 0; 2026 par->lock_blank = 0;
1848 2027
2028#ifdef CONFIG_FB_ATY128_BACKLIGHT
2029 aty128_bl_init(par);
2030#endif
2031
1849 printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", 2032 printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
1850 info->node, info->fix.id, video_card); 2033 info->node, info->fix.id, video_card);
1851 2034
@@ -1981,6 +2164,10 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
1981 2164
1982 par = info->par; 2165 par = info->par;
1983 2166
2167#ifdef CONFIG_FB_ATY128_BACKLIGHT
2168 aty128_bl_exit(par);
2169#endif
2170
1984 unregister_framebuffer(info); 2171 unregister_framebuffer(info);
1985#ifdef CONFIG_MTRR 2172#ifdef CONFIG_MTRR
1986 if (par->mtrr.vram_valid) 2173 if (par->mtrr.vram_valid)
@@ -2011,10 +2198,14 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
2011 if (par->lock_blank || par->asleep) 2198 if (par->lock_blank || par->asleep)
2012 return 0; 2199 return 0;
2013 2200
2014#ifdef CONFIG_PMAC_BACKLIGHT 2201#ifdef CONFIG_FB_ATY128_BACKLIGHT
2015 if (machine_is(powermac) && blank) 2202 if (machine_is(powermac) && blank) {
2016 set_backlight_enable(0); 2203 down(&fb->bl_dev->sem);
2017#endif /* CONFIG_PMAC_BACKLIGHT */ 2204 fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
2205 fb->bl_dev->props->update_status(fb->bl_dev);
2206 up(&fb->bl_dev->sem);
2207 }
2208#endif
2018 2209
2019 if (blank & FB_BLANK_VSYNC_SUSPEND) 2210 if (blank & FB_BLANK_VSYNC_SUSPEND)
2020 state |= 2; 2211 state |= 2;
@@ -2029,10 +2220,14 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
2029 aty128_set_crt_enable(par, par->crt_on && !blank); 2220 aty128_set_crt_enable(par, par->crt_on && !blank);
2030 aty128_set_lcd_enable(par, par->lcd_on && !blank); 2221 aty128_set_lcd_enable(par, par->lcd_on && !blank);
2031 } 2222 }
2032#ifdef CONFIG_PMAC_BACKLIGHT 2223#ifdef CONFIG_FB_ATY128_BACKLIGHT
2033 if (machine_is(powermac) && !blank) 2224 if (machine_is(powermac) && !blank) {
2034 set_backlight_enable(1); 2225 down(&fb->bl_dev->sem);
2035#endif /* CONFIG_PMAC_BACKLIGHT */ 2226 fb->bl_dev->props->power = FB_BLANK_UNBLANK;
2227 fb->bl_dev->props->update_status(fb->bl_dev);
2228 up(&fb->bl_dev->sem);
2229 }
2230#endif
2036 return 0; 2231 return 0;
2037} 2232}
2038 2233
@@ -2138,73 +2333,6 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
2138 return -EINVAL; 2333 return -EINVAL;
2139} 2334}
2140 2335
2141#ifdef CONFIG_PMAC_BACKLIGHT
2142static int backlight_conv[] = {
2143 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
2144 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
2145};
2146
2147/* We turn off the LCD completely instead of just dimming the backlight.
2148 * This provides greater power saving and the display is useless without
2149 * backlight anyway
2150 */
2151#define BACKLIGHT_LVDS_OFF
2152/* That one prevents proper CRT output with LCD off */
2153#undef BACKLIGHT_DAC_OFF
2154
2155static int aty128_set_backlight_enable(int on, int level, void *data)
2156{
2157 struct aty128fb_par *par = data;
2158 unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
2159
2160 if (!par->lcd_on)
2161 on = 0;
2162 reg |= LVDS_BL_MOD_EN | LVDS_BLON;
2163 if (on && level > BACKLIGHT_OFF) {
2164 reg |= LVDS_DIGION;
2165 if (!(reg & LVDS_ON)) {
2166 reg &= ~LVDS_BLON;
2167 aty_st_le32(LVDS_GEN_CNTL, reg);
2168 (void)aty_ld_le32(LVDS_GEN_CNTL);
2169 mdelay(10);
2170 reg |= LVDS_BLON;
2171 aty_st_le32(LVDS_GEN_CNTL, reg);
2172 }
2173 reg &= ~LVDS_BL_MOD_LEVEL_MASK;
2174 reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT);
2175#ifdef BACKLIGHT_LVDS_OFF
2176 reg |= LVDS_ON | LVDS_EN;
2177 reg &= ~LVDS_DISPLAY_DIS;
2178#endif
2179 aty_st_le32(LVDS_GEN_CNTL, reg);
2180#ifdef BACKLIGHT_DAC_OFF
2181 aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
2182#endif
2183 } else {
2184 reg &= ~LVDS_BL_MOD_LEVEL_MASK;
2185 reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT);
2186#ifdef BACKLIGHT_LVDS_OFF
2187 reg |= LVDS_DISPLAY_DIS;
2188 aty_st_le32(LVDS_GEN_CNTL, reg);
2189 (void)aty_ld_le32(LVDS_GEN_CNTL);
2190 udelay(10);
2191 reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
2192#endif
2193 aty_st_le32(LVDS_GEN_CNTL, reg);
2194#ifdef BACKLIGHT_DAC_OFF
2195 aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
2196#endif
2197 }
2198
2199 return 0;
2200}
2201
2202static int aty128_set_backlight_level(int level, void* data)
2203{
2204 return aty128_set_backlight_enable(1, level, data);
2205}
2206#endif /* CONFIG_PMAC_BACKLIGHT */
2207
2208#if 0 2336#if 0
2209 /* 2337 /*
2210 * Accelerated functions 2338 * Accelerated functions
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index e9b7a64c1ac4..43d2cb58af87 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -151,6 +151,7 @@ struct atyfb_par {
151 int lock_blank; 151 int lock_blank;
152 unsigned long res_start; 152 unsigned long res_start;
153 unsigned long res_size; 153 unsigned long res_size;
154 struct pci_dev *pdev;
154#ifdef __sparc__ 155#ifdef __sparc__
155 struct pci_mmap_map *mmap_map; 156 struct pci_mmap_map *mmap_map;
156 u8 mmaped; 157 u8 mmaped;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index d9d7d3c4cae2..c5185f7cf4ba 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -66,6 +66,7 @@
66#include <linux/interrupt.h> 66#include <linux/interrupt.h>
67#include <linux/spinlock.h> 67#include <linux/spinlock.h>
68#include <linux/wait.h> 68#include <linux/wait.h>
69#include <linux/backlight.h>
69 70
70#include <asm/io.h> 71#include <asm/io.h>
71#include <asm/uaccess.h> 72#include <asm/uaccess.h>
@@ -2115,45 +2116,142 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
2115 2116
2116#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ 2117#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */
2117 2118
2118#ifdef CONFIG_PMAC_BACKLIGHT 2119/* Backlight */
2120#ifdef CONFIG_FB_ATY_BACKLIGHT
2121#define MAX_LEVEL 0xFF
2119 2122
2120 /* 2123static struct backlight_properties aty_bl_data;
2121 * LCD backlight control
2122 */
2123 2124
2124static int backlight_conv[] = { 2125static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2125 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d, 2126{
2126 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff 2127 struct fb_info *info = pci_get_drvdata(par->pdev);
2127}; 2128 int atylevel;
2129
2130 /* Get and convert the value */
2131 mutex_lock(&info->bl_mutex);
2132 atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
2133 mutex_unlock(&info->bl_mutex);
2128 2134
2129static int aty_set_backlight_enable(int on, int level, void *data) 2135 if (atylevel < 0)
2136 atylevel = 0;
2137 else if (atylevel > MAX_LEVEL)
2138 atylevel = MAX_LEVEL;
2139
2140 return atylevel;
2141}
2142
2143static int aty_bl_update_status(struct backlight_device *bd)
2130{ 2144{
2131 struct fb_info *info = (struct fb_info *) data; 2145 struct atyfb_par *par = class_get_devdata(&bd->class_dev);
2132 struct atyfb_par *par = (struct atyfb_par *) info->par;
2133 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par); 2146 unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
2147 int level;
2148
2149 if (bd->props->power != FB_BLANK_UNBLANK ||
2150 bd->props->fb_blank != FB_BLANK_UNBLANK)
2151 level = 0;
2152 else
2153 level = bd->props->brightness;
2134 2154
2135 reg |= (BLMOD_EN | BIASMOD_EN); 2155 reg |= (BLMOD_EN | BIASMOD_EN);
2136 if (on && level > BACKLIGHT_OFF) { 2156 if (level > 0) {
2137 reg &= ~BIAS_MOD_LEVEL_MASK; 2157 reg &= ~BIAS_MOD_LEVEL_MASK;
2138 reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT); 2158 reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
2139 } else { 2159 } else {
2140 reg &= ~BIAS_MOD_LEVEL_MASK; 2160 reg &= ~BIAS_MOD_LEVEL_MASK;
2141 reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT); 2161 reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
2142 } 2162 }
2143 aty_st_lcd(LCD_MISC_CNTL, reg, par); 2163 aty_st_lcd(LCD_MISC_CNTL, reg, par);
2164
2144 return 0; 2165 return 0;
2145} 2166}
2146 2167
2147static int aty_set_backlight_level(int level, void *data) 2168static int aty_bl_get_brightness(struct backlight_device *bd)
2148{ 2169{
2149 return aty_set_backlight_enable(1, level, data); 2170 return bd->props->brightness;
2150} 2171}
2151 2172
2152static struct backlight_controller aty_backlight_controller = { 2173static struct backlight_properties aty_bl_data = {
2153 aty_set_backlight_enable, 2174 .owner = THIS_MODULE,
2154 aty_set_backlight_level 2175 .get_brightness = aty_bl_get_brightness,
2176 .update_status = aty_bl_update_status,
2177 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
2155}; 2178};
2156#endif /* CONFIG_PMAC_BACKLIGHT */ 2179
2180static void aty_bl_init(struct atyfb_par *par)
2181{
2182 struct fb_info *info = pci_get_drvdata(par->pdev);
2183 struct backlight_device *bd;
2184 char name[12];
2185
2186#ifdef CONFIG_PMAC_BACKLIGHT
2187 if (!pmac_has_backlight_type("ati"))
2188 return;
2189#endif
2190
2191 snprintf(name, sizeof(name), "atybl%d", info->node);
2192
2193 bd = backlight_device_register(name, par, &aty_bl_data);
2194 if (IS_ERR(bd)) {
2195 info->bl_dev = NULL;
2196 printk("aty: Backlight registration failed\n");
2197 goto error;
2198 }
2199
2200 mutex_lock(&info->bl_mutex);
2201 info->bl_dev = bd;
2202 fb_bl_default_curve(info, 0,
2203 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2204 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2205 mutex_unlock(&info->bl_mutex);
2206
2207 up(&bd->sem);
2208 bd->props->brightness = aty_bl_data.max_brightness;
2209 bd->props->power = FB_BLANK_UNBLANK;
2210 bd->props->update_status(bd);
2211 down(&bd->sem);
2212
2213#ifdef CONFIG_PMAC_BACKLIGHT
2214 mutex_lock(&pmac_backlight_mutex);
2215 if (!pmac_backlight)
2216 pmac_backlight = bd;
2217 mutex_unlock(&pmac_backlight_mutex);
2218#endif
2219
2220 printk("aty: Backlight initialized (%s)\n", name);
2221
2222 return;
2223
2224error:
2225 return;
2226}
2227
2228static void aty_bl_exit(struct atyfb_par *par)
2229{
2230 struct fb_info *info = pci_get_drvdata(par->pdev);
2231
2232#ifdef CONFIG_PMAC_BACKLIGHT
2233 mutex_lock(&pmac_backlight_mutex);
2234#endif
2235
2236 mutex_lock(&info->bl_mutex);
2237 if (info->bl_dev) {
2238#ifdef CONFIG_PMAC_BACKLIGHT
2239 if (pmac_backlight == info->bl_dev)
2240 pmac_backlight = NULL;
2241#endif
2242
2243 backlight_device_unregister(info->bl_dev);
2244
2245 printk("aty: Backlight unloaded\n");
2246 }
2247 mutex_unlock(&info->bl_mutex);
2248
2249#ifdef CONFIG_PMAC_BACKLIGHT
2250 mutex_unlock(&pmac_backlight_mutex);
2251#endif
2252}
2253
2254#endif /* CONFIG_FB_ATY_BACKLIGHT */
2157 2255
2158static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) 2256static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2159{ 2257{
@@ -2513,9 +2611,13 @@ static int __init aty_init(struct fb_info *info, const char *name)
2513 /* these bits let the 101 powerbook wake up from sleep -- paulus */ 2611 /* these bits let the 101 powerbook wake up from sleep -- paulus */
2514 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) 2612 aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
2515 | (USE_F32KHZ | TRISTATE_MEM_EN), par); 2613 | (USE_F32KHZ | TRISTATE_MEM_EN), par);
2516 } else if (M64_HAS(MOBIL_BUS)) 2614 } else
2517 register_backlight_controller(&aty_backlight_controller, info, "ati"); 2615#endif
2518#endif /* CONFIG_PMAC_BACKLIGHT */ 2616 if (M64_HAS(MOBIL_BUS)) {
2617#ifdef CONFIG_FB_ATY_BACKLIGHT
2618 aty_bl_init (par);
2619#endif
2620 }
2519 2621
2520 memset(&var, 0, sizeof(var)); 2622 memset(&var, 0, sizeof(var));
2521#ifdef CONFIG_PPC 2623#ifdef CONFIG_PPC
@@ -2674,8 +2776,16 @@ static int atyfb_blank(int blank, struct fb_info *info)
2674 return 0; 2776 return 0;
2675 2777
2676#ifdef CONFIG_PMAC_BACKLIGHT 2778#ifdef CONFIG_PMAC_BACKLIGHT
2677 if (machine_is(powermac) && blank > FB_BLANK_NORMAL) 2779 if (machine_is(powermac) && blank > FB_BLANK_NORMAL) {
2678 set_backlight_enable(0); 2780 mutex_lock(&info->bl_mutex);
2781 if (info->bl_dev) {
2782 down(&info->bl_dev->sem);
2783 info->bl_dev->props->power = FB_BLANK_POWERDOWN;
2784 info->bl_dev->props->update_status(info->bl_dev);
2785 up(&info->bl_dev->sem);
2786 }
2787 mutex_unlock(&info->bl_mutex);
2788 }
2679#elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2789#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2680 if (par->lcd_table && blank > FB_BLANK_NORMAL && 2790 if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2681 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2791 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2706,8 +2816,16 @@ static int atyfb_blank(int blank, struct fb_info *info)
2706 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); 2816 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2707 2817
2708#ifdef CONFIG_PMAC_BACKLIGHT 2818#ifdef CONFIG_PMAC_BACKLIGHT
2709 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) 2819 if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) {
2710 set_backlight_enable(1); 2820 mutex_lock(&info->bl_mutex);
2821 if (info->bl_dev) {
2822 down(&info->bl_dev->sem);
2823 info->bl_dev->props->power = FB_BLANK_UNBLANK;
2824 info->bl_dev->props->update_status(info->bl_dev);
2825 up(&info->bl_dev->sem);
2826 }
2827 mutex_unlock(&info->bl_mutex);
2828 }
2711#elif defined(CONFIG_FB_ATY_GENERIC_LCD) 2829#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2712 if (par->lcd_table && blank <= FB_BLANK_NORMAL && 2830 if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2713 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2831 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2966,7 +3084,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2966 } 3084 }
2967 3085
2968 pcp = pdev->sysdata; 3086 pcp = pdev->sysdata;
2969 if (node == pcp->prom_node) { 3087 if (node == pcp->prom_node->node) {
2970 struct fb_var_screeninfo *var = &default_var; 3088 struct fb_var_screeninfo *var = &default_var;
2971 unsigned int N, P, Q, M, T, R; 3089 unsigned int N, P, Q, M, T, R;
2972 u32 v_total, h_total; 3090 u32 v_total, h_total;
@@ -3440,6 +3558,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3440 par->res_start = res_start; 3558 par->res_start = res_start;
3441 par->res_size = res_size; 3559 par->res_size = res_size;
3442 par->irq = pdev->irq; 3560 par->irq = pdev->irq;
3561 par->pdev = pdev;
3443 3562
3444 /* Setup "info" structure */ 3563 /* Setup "info" structure */
3445#ifdef __sparc__ 3564#ifdef __sparc__
@@ -3571,6 +3690,11 @@ static void __devexit atyfb_remove(struct fb_info *info)
3571 aty_set_crtc(par, &saved_crtc); 3690 aty_set_crtc(par, &saved_crtc);
3572 par->pll_ops->set_pll(info, &saved_pll); 3691 par->pll_ops->set_pll(info, &saved_pll);
3573 3692
3693#ifdef CONFIG_FB_ATY_BACKLIGHT
3694 if (M64_HAS(MOBIL_BUS))
3695 aty_bl_exit(par);
3696#endif
3697
3574 unregister_framebuffer(info); 3698 unregister_framebuffer(info);
3575 3699
3576#ifdef CONFIG_MTRR 3700#ifdef CONFIG_MTRR
@@ -3722,7 +3846,9 @@ static int __init atyfb_init(void)
3722 atyfb_setup(option); 3846 atyfb_setup(option);
3723#endif 3847#endif
3724 3848
3849#ifdef CONFIG_PCI
3725 pci_register_driver(&atyfb_driver); 3850 pci_register_driver(&atyfb_driver);
3851#endif
3726#ifdef CONFIG_ATARI 3852#ifdef CONFIG_ATARI
3727 atyfb_atari_probe(); 3853 atyfb_atari_probe();
3728#endif 3854#endif
@@ -3731,7 +3857,9 @@ static int __init atyfb_init(void)
3731 3857
3732static void __exit atyfb_exit(void) 3858static void __exit atyfb_exit(void)
3733{ 3859{
3860#ifdef CONFIG_PCI
3734 pci_unregister_driver(&atyfb_driver); 3861 pci_unregister_driver(&atyfb_driver);
3862#endif
3735} 3863}
3736 3864
3737module_init(atyfb_init); 3865module_init(atyfb_init);
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
new file mode 100644
index 000000000000..7de66b855d4e
--- /dev/null
+++ b/drivers/video/aty/radeon_backlight.c
@@ -0,0 +1,247 @@
1/*
2 * Backlight code for ATI Radeon based graphic cards
3 *
4 * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
5 * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
6 * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
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#include "radeonfb.h"
14#include <linux/backlight.h>
15
16#ifdef CONFIG_PMAC_BACKLIGHT
17#include <asm/backlight.h>
18#endif
19
20#define MAX_RADEON_LEVEL 0xFF
21
22static struct backlight_properties radeon_bl_data;
23
24struct radeon_bl_privdata {
25 struct radeonfb_info *rinfo;
26 uint8_t negative;
27};
28
29static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
30 int level)
31{
32 struct fb_info *info = pdata->rinfo->info;
33 int rlevel;
34
35 mutex_lock(&info->bl_mutex);
36
37 /* Get and convert the value */
38 rlevel = pdata->rinfo->info->bl_curve[level] *
39 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
40
41 mutex_unlock(&info->bl_mutex);
42
43 if (pdata->negative)
44 rlevel = MAX_RADEON_LEVEL - rlevel;
45
46 if (rlevel < 0)
47 rlevel = 0;
48 else if (rlevel > MAX_RADEON_LEVEL)
49 rlevel = MAX_RADEON_LEVEL;
50
51 return rlevel;
52}
53
54static int radeon_bl_update_status(struct backlight_device *bd)
55{
56 struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev);
57 struct radeonfb_info *rinfo = pdata->rinfo;
58 u32 lvds_gen_cntl, tmpPixclksCntl;
59 int level;
60
61 if (rinfo->mon1_type != MT_LCD)
62 return 0;
63
64 /* We turn off the LCD completely instead of just dimming the
65 * backlight. This provides some greater power saving and the display
66 * is useless without backlight anyway.
67 */
68 if (bd->props->power != FB_BLANK_UNBLANK ||
69 bd->props->fb_blank != FB_BLANK_UNBLANK)
70 level = 0;
71 else
72 level = bd->props->brightness;
73
74 del_timer_sync(&rinfo->lvds_timer);
75 radeon_engine_idle();
76
77 lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
78 if (level > 0) {
79 lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
80 if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
81 lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
82 lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
83 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
84 lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
85 lvds_gen_cntl |=
86 (radeon_bl_get_level_brightness(pdata, level) <<
87 LVDS_BL_MOD_LEVEL_SHIFT);
88 lvds_gen_cntl |= LVDS_ON;
89 lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
90 rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
91 mod_timer(&rinfo->lvds_timer,
92 jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
93 } else {
94 lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
95 lvds_gen_cntl |=
96 (radeon_bl_get_level_brightness(pdata, level) <<
97 LVDS_BL_MOD_LEVEL_SHIFT);
98 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
99 }
100 rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
101 rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
102 & LVDS_STATE_MASK;
103 } else {
104 /* Asic bug, when turning off LVDS_ON, we have to make sure
105 RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
106 */
107 tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
108 if (rinfo->is_mobility || rinfo->is_IGP)
109 OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
110 lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
111 lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
112 LVDS_BL_MOD_LEVEL_SHIFT);
113 lvds_gen_cntl |= LVDS_DISPLAY_DIS;
114 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
115 udelay(100);
116 lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
117 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
118 lvds_gen_cntl &= ~(LVDS_DIGON);
119 rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
120 mod_timer(&rinfo->lvds_timer,
121 jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
122 if (rinfo->is_mobility || rinfo->is_IGP)
123 OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
124 }
125 rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
126 rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
127
128 return 0;
129}
130
131static int radeon_bl_get_brightness(struct backlight_device *bd)
132{
133 return bd->props->brightness;
134}
135
136static struct backlight_properties radeon_bl_data = {
137 .owner = THIS_MODULE,
138 .get_brightness = radeon_bl_get_brightness,
139 .update_status = radeon_bl_update_status,
140 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
141};
142
143void radeonfb_bl_init(struct radeonfb_info *rinfo)
144{
145 struct backlight_device *bd;
146 struct radeon_bl_privdata *pdata;
147 char name[12];
148
149 if (rinfo->mon1_type != MT_LCD)
150 return;
151
152#ifdef CONFIG_PMAC_BACKLIGHT
153 if (!pmac_has_backlight_type("ati") &&
154 !pmac_has_backlight_type("mnca"))
155 return;
156#endif
157
158 pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
159 if (!pdata) {
160 printk("radeonfb: Memory allocation failed\n");
161 goto error;
162 }
163
164 snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
165
166 bd = backlight_device_register(name, pdata, &radeon_bl_data);
167 if (IS_ERR(bd)) {
168 rinfo->info->bl_dev = NULL;
169 printk("radeonfb: Backlight registration failed\n");
170 goto error;
171 }
172
173 pdata->rinfo = rinfo;
174
175 /* Pardon me for that hack... maybe some day we can figure out in what
176 * direction backlight should work on a given panel?
177 */
178 pdata->negative =
179 (rinfo->family != CHIP_FAMILY_RV200 &&
180 rinfo->family != CHIP_FAMILY_RV250 &&
181 rinfo->family != CHIP_FAMILY_RV280 &&
182 rinfo->family != CHIP_FAMILY_RV350);
183
184#ifdef CONFIG_PMAC_BACKLIGHT
185 pdata->negative = pdata->negative ||
186 machine_is_compatible("PowerBook4,3") ||
187 machine_is_compatible("PowerBook6,3") ||
188 machine_is_compatible("PowerBook6,5");
189#endif
190
191 mutex_lock(&rinfo->info->bl_mutex);
192 rinfo->info->bl_dev = bd;
193 fb_bl_default_curve(rinfo->info, 0,
194 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
195 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
196 mutex_unlock(&rinfo->info->bl_mutex);
197
198 up(&bd->sem);
199 bd->props->brightness = radeon_bl_data.max_brightness;
200 bd->props->power = FB_BLANK_UNBLANK;
201 bd->props->update_status(bd);
202 down(&bd->sem);
203
204#ifdef CONFIG_PMAC_BACKLIGHT
205 mutex_lock(&pmac_backlight_mutex);
206 if (!pmac_backlight)
207 pmac_backlight = bd;
208 mutex_unlock(&pmac_backlight_mutex);
209#endif
210
211 printk("radeonfb: Backlight initialized (%s)\n", name);
212
213 return;
214
215error:
216 kfree(pdata);
217 return;
218}
219
220void radeonfb_bl_exit(struct radeonfb_info *rinfo)
221{
222#ifdef CONFIG_PMAC_BACKLIGHT
223 mutex_lock(&pmac_backlight_mutex);
224#endif
225
226 mutex_lock(&rinfo->info->bl_mutex);
227 if (rinfo->info->bl_dev) {
228 struct radeon_bl_privdata *pdata;
229
230#ifdef CONFIG_PMAC_BACKLIGHT
231 if (pmac_backlight == rinfo->info->bl_dev)
232 pmac_backlight = NULL;
233#endif
234
235 pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
236 backlight_device_unregister(rinfo->info->bl_dev);
237 kfree(pdata);
238 rinfo->info->bl_dev = NULL;
239
240 printk("radeonfb: Backlight unloaded\n");
241 }
242 mutex_unlock(&rinfo->info->bl_mutex);
243
244#ifdef CONFIG_PMAC_BACKLIGHT
245 mutex_unlock(&pmac_backlight_mutex);
246#endif
247}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 387a18a47ac2..c5ecbb02e01d 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -78,10 +78,6 @@
78#include <asm/pci-bridge.h> 78#include <asm/pci-bridge.h>
79#include "../macmodes.h" 79#include "../macmodes.h"
80 80
81#ifdef CONFIG_PMAC_BACKLIGHT
82#include <asm/backlight.h>
83#endif
84
85#ifdef CONFIG_BOOTX_TEXT 81#ifdef CONFIG_BOOTX_TEXT
86#include <asm/btext.h> 82#include <asm/btext.h>
87#endif 83#endif
@@ -277,20 +273,6 @@ static int nomtrr = 0;
277 * prototypes 273 * prototypes
278 */ 274 */
279 275
280
281#ifdef CONFIG_PPC_OF
282
283#ifdef CONFIG_PMAC_BACKLIGHT
284static int radeon_set_backlight_enable(int on, int level, void *data);
285static int radeon_set_backlight_level(int level, void *data);
286static struct backlight_controller radeon_backlight_controller = {
287 radeon_set_backlight_enable,
288 radeon_set_backlight_level
289};
290#endif /* CONFIG_PMAC_BACKLIGHT */
291
292#endif /* CONFIG_PPC_OF */
293
294static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) 276static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
295{ 277{
296 if (!rinfo->bios_seg) 278 if (!rinfo->bios_seg)
@@ -1913,116 +1895,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
1913 return 0; 1895 return 0;
1914} 1896}
1915 1897
1916
1917#ifdef CONFIG_PMAC_BACKLIGHT
1918
1919/* TODO: Dbl check these tables, we don't go up to full ON backlight
1920 * in these, possibly because we noticed MacOS doesn't, but I'd prefer
1921 * having some more official numbers from ATI
1922 */
1923static int backlight_conv_m6[] = {
1924 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
1925 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
1926};
1927static int backlight_conv_m7[] = {
1928 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,
1929 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9
1930};
1931
1932#define BACKLIGHT_LVDS_OFF
1933#undef BACKLIGHT_DAC_OFF
1934
1935/* We turn off the LCD completely instead of just dimming the backlight.
1936 * This provides some greater power saving and the display is useless
1937 * without backlight anyway.
1938 */
1939static int radeon_set_backlight_enable(int on, int level, void *data)
1940{
1941 struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
1942 u32 lvds_gen_cntl, tmpPixclksCntl;
1943 int* conv_table;
1944
1945 if (rinfo->mon1_type != MT_LCD)
1946 return 0;
1947
1948 /* Pardon me for that hack... maybe some day we can figure
1949 * out in what direction backlight should work on a given
1950 * panel ?
1951 */
1952 if ((rinfo->family == CHIP_FAMILY_RV200 ||
1953 rinfo->family == CHIP_FAMILY_RV250 ||
1954 rinfo->family == CHIP_FAMILY_RV280 ||
1955 rinfo->family == CHIP_FAMILY_RV350) &&
1956 !machine_is_compatible("PowerBook4,3") &&
1957 !machine_is_compatible("PowerBook6,3") &&
1958 !machine_is_compatible("PowerBook6,5"))
1959 conv_table = backlight_conv_m7;
1960 else
1961 conv_table = backlight_conv_m6;
1962
1963 del_timer_sync(&rinfo->lvds_timer);
1964 radeon_engine_idle();
1965
1966 lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
1967 if (on && (level > BACKLIGHT_OFF)) {
1968 lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
1969 if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
1970 lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
1971 lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
1972 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
1973 lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
1974 lvds_gen_cntl |= (conv_table[level] <<
1975 LVDS_BL_MOD_LEVEL_SHIFT);
1976 lvds_gen_cntl |= LVDS_ON;
1977 lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
1978 rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
1979 mod_timer(&rinfo->lvds_timer,
1980 jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
1981 } else {
1982 lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
1983 lvds_gen_cntl |= (conv_table[level] <<
1984 LVDS_BL_MOD_LEVEL_SHIFT);
1985 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
1986 }
1987 rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
1988 rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
1989 & LVDS_STATE_MASK;
1990 } else {
1991 /* Asic bug, when turning off LVDS_ON, we have to make sure
1992 RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
1993 */
1994 tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
1995 if (rinfo->is_mobility || rinfo->is_IGP)
1996 OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
1997 lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
1998 lvds_gen_cntl |= (conv_table[0] <<
1999 LVDS_BL_MOD_LEVEL_SHIFT);
2000 lvds_gen_cntl |= LVDS_DISPLAY_DIS;
2001 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
2002 udelay(100);
2003 lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
2004 OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
2005 lvds_gen_cntl &= ~(LVDS_DIGON);
2006 rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
2007 mod_timer(&rinfo->lvds_timer,
2008 jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
2009 if (rinfo->is_mobility || rinfo->is_IGP)
2010 OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
2011 }
2012 rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
2013 rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
2014
2015 return 0;
2016}
2017
2018
2019static int radeon_set_backlight_level(int level, void *data)
2020{
2021 return radeon_set_backlight_enable(1, level, data);
2022}
2023#endif /* CONFIG_PMAC_BACKLIGHT */
2024
2025
2026/* 1898/*
2027 * This reconfigure the card's internal memory map. In theory, we'd like 1899 * This reconfigure the card's internal memory map. In theory, we'd like
2028 * to setup the card's memory at the same address as it's PCI bus address, 1900 * to setup the card's memory at the same address as it's PCI bus address,
@@ -2477,14 +2349,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
2477 MTRR_TYPE_WRCOMB, 1); 2349 MTRR_TYPE_WRCOMB, 1);
2478#endif 2350#endif
2479 2351
2480#ifdef CONFIG_PMAC_BACKLIGHT 2352 radeonfb_bl_init(rinfo);
2481 if (rinfo->mon1_type == MT_LCD) {
2482 register_backlight_controller(&radeon_backlight_controller,
2483 rinfo, "ati");
2484 register_backlight_controller(&radeon_backlight_controller,
2485 rinfo, "mnca");
2486 }
2487#endif
2488 2353
2489 printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); 2354 printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
2490 2355
@@ -2528,7 +2393,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
2528 2393
2529 if (!rinfo) 2394 if (!rinfo)
2530 return; 2395 return;
2531 2396
2397 radeonfb_bl_exit(rinfo);
2532 radeonfb_pm_exit(rinfo); 2398 radeonfb_pm_exit(rinfo);
2533 2399
2534 if (rinfo->mon1_EDID) 2400 if (rinfo->mon1_EDID)
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 217e00ab4a2d..1645943b1123 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -625,4 +625,13 @@ extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_
625extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, 625extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
626 int reg_only); 626 int reg_only);
627 627
628/* Backlight functions */
629#ifdef CONFIG_FB_RADEON_BACKLIGHT
630extern void radeonfb_bl_init(struct radeonfb_info *rinfo);
631extern void radeonfb_bl_exit(struct radeonfb_info *rinfo);
632#else
633static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {}
634static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {}
635#endif
636
628#endif /* __RADEONFB_H__ */ 637#endif /* __RADEONFB_H__ */
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 3d04b2def0f1..789450bb0bc9 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -214,10 +214,13 @@ int au1100fb_setmode(struct au1100fb_device *fbdev)
214 */ 214 */
215int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi) 215int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
216{ 216{
217 struct au1100fb_device *fbdev = to_au1100fb_device(fbi); 217 struct au1100fb_device *fbdev;
218 u32 *palette = fbdev->regs->lcd_pallettebase; 218 u32 *palette;
219 u32 value; 219 u32 value;
220 220
221 fbdev = to_au1100fb_device(fbi);
222 palette = fbdev->regs->lcd_pallettebase;
223
221 if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1)) 224 if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
222 return -EINVAL; 225 return -EINVAL;
223 226
@@ -316,9 +319,11 @@ int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
316 */ 319 */
317int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) 320int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
318{ 321{
319 struct au1100fb_device *fbdev = to_au1100fb_device(fbi); 322 struct au1100fb_device *fbdev;
320 int dy; 323 int dy;
321 324
325 fbdev = to_au1100fb_device(fbi);
326
322 print_dbg("fb_pan_display %p %p", var, fbi); 327 print_dbg("fb_pan_display %p %p", var, fbi);
323 328
324 if (!var || !fbdev) { 329 if (!var || !fbdev) {
@@ -382,10 +387,12 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
382 */ 387 */
383int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) 388int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
384{ 389{
385 struct au1100fb_device *fbdev = to_au1100fb_device(fbi); 390 struct au1100fb_device *fbdev;
386 unsigned int len; 391 unsigned int len;
387 unsigned long start=0, off; 392 unsigned long start=0, off;
388 393
394 fbdev = to_au1100fb_device(fbi);
395
389 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { 396 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
390 return -EINVAL; 397 return -EINVAL;
391 } 398 }
@@ -467,7 +474,7 @@ int au1100fb_drv_probe(struct device *dev)
467 474
468 if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, 475 if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len,
469 DRIVER_NAME)) { 476 DRIVER_NAME)) {
470 print_err("fail to lock memory region at 0x%08x", 477 print_err("fail to lock memory region at 0x%08lx",
471 au1100fb_fix.mmio_start); 478 au1100fb_fix.mmio_start);
472 return -EBUSY; 479 return -EBUSY;
473 } 480 }
@@ -595,13 +602,13 @@ int au1100fb_drv_remove(struct device *dev)
595 return 0; 602 return 0;
596} 603}
597 604
598int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level) 605int au1100fb_drv_suspend(struct device *dev, pm_message_t state)
599{ 606{
600 /* TODO */ 607 /* TODO */
601 return 0; 608 return 0;
602} 609}
603 610
604int au1100fb_drv_resume(struct device *dev, u32 level) 611int au1100fb_drv_resume(struct device *dev)
605{ 612{
606 /* TODO */ 613 /* TODO */
607 return 0; 614 return 0;
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 72ff6bf75e5e..d76bbfac92cc 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -148,9 +148,24 @@ static int chipsfb_set_par(struct fb_info *info)
148static int chipsfb_blank(int blank, struct fb_info *info) 148static int chipsfb_blank(int blank, struct fb_info *info)
149{ 149{
150#ifdef CONFIG_PMAC_BACKLIGHT 150#ifdef CONFIG_PMAC_BACKLIGHT
151 // used to disable backlight only for blank > 1, but it seems 151 mutex_lock(&pmac_backlight_mutex);
152 // useful at blank = 1 too (saves battery, extends backlight life) 152
153 set_backlight_enable(!blank); 153 if (pmac_backlight) {
154 down(&pmac_backlight->sem);
155
156 /* used to disable backlight only for blank > 1, but it seems
157 * useful at blank = 1 too (saves battery, extends backlight
158 * life)
159 */
160 if (blank)
161 pmac_backlight->props->power = FB_BLANK_POWERDOWN;
162 else
163 pmac_backlight->props->power = FB_BLANK_UNBLANK;
164 pmac_backlight->props->update_status(pmac_backlight);
165 up(&pmac_backlight->sem);
166 }
167
168 mutex_unlock(&pmac_backlight_mutex);
154#endif /* CONFIG_PMAC_BACKLIGHT */ 169#endif /* CONFIG_PMAC_BACKLIGHT */
155 170
156 return 1; /* get fb_blank to set the colormap to all black */ 171 return 1; /* get fb_blank to set the colormap to all black */
@@ -401,7 +416,14 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
401 416
402#ifdef CONFIG_PMAC_BACKLIGHT 417#ifdef CONFIG_PMAC_BACKLIGHT
403 /* turn on the backlight */ 418 /* turn on the backlight */
404 set_backlight_enable(1); 419 mutex_lock(&pmac_backlight_mutex);
420 if (pmac_backlight) {
421 down(&pmac_backlight->sem);
422 pmac_backlight->props->power = FB_BLANK_UNBLANK;
423 pmac_backlight->props->update_status(pmac_backlight);
424 up(&pmac_backlight->sem);
425 }
426 mutex_unlock(&pmac_backlight_mutex);
405#endif /* CONFIG_PMAC_BACKLIGHT */ 427#endif /* CONFIG_PMAC_BACKLIGHT */
406 428
407#ifdef CONFIG_PPC 429#ifdef CONFIG_PPC
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index ca020719d20b..47ba1a79adcd 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1745,7 +1745,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
1745 fbcon_redraw_move(vc, p, 0, t, count); 1745 fbcon_redraw_move(vc, p, 0, t, count);
1746 ypan_up_redraw(vc, t, count); 1746 ypan_up_redraw(vc, t, count);
1747 if (vc->vc_rows - b > 0) 1747 if (vc->vc_rows - b > 0)
1748 fbcon_redraw_move(vc, p, b - count, 1748 fbcon_redraw_move(vc, p, b,
1749 vc->vc_rows - b, b); 1749 vc->vc_rows - b, b);
1750 } else 1750 } else
1751 fbcon_redraw_move(vc, p, t + count, b - t - count, t); 1751 fbcon_redraw_move(vc, p, t + count, b - t - count, t);
@@ -2631,7 +2631,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
2631 scr_memcpyw((u16 *) q, (u16 *) p, 2631 scr_memcpyw((u16 *) q, (u16 *) p,
2632 vc->vc_size_row); 2632 vc->vc_size_row);
2633 } 2633 }
2634 softback_in = p; 2634 softback_in = softback_curr = p;
2635 update_region(vc, vc->vc_origin, 2635 update_region(vc, vc->vc_origin,
2636 logo_lines * vc->vc_cols); 2636 logo_lines * vc->vc_cols);
2637 } 2637 }
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 989e4d49e5bb..7f939d066a5a 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -313,8 +313,8 @@ static const char __init *mdacon_startup(void)
313 mda_num_columns = 80; 313 mda_num_columns = 80;
314 mda_num_lines = 25; 314 mda_num_lines = 25;
315 315
316 mda_vram_base = VGA_MAP_MEM(0xb0000);
317 mda_vram_len = 0x01000; 316 mda_vram_len = 0x01000;
317 mda_vram_base = VGA_MAP_MEM(0xb0000, mda_vram_len);
318 318
319 mda_index_port = 0x3b4; 319 mda_index_port = 0x3b4;
320 mda_value_port = 0x3b5; 320 mda_value_port = 0x3b5;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d5a04b68c4d4..e64d42e2449e 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -391,7 +391,7 @@ static const char __init *vgacon_startup(void)
391 static struct resource ega_console_resource = 391 static struct resource ega_console_resource =
392 { "ega", 0x3B0, 0x3BF }; 392 { "ega", 0x3B0, 0x3BF };
393 vga_video_type = VIDEO_TYPE_EGAM; 393 vga_video_type = VIDEO_TYPE_EGAM;
394 vga_vram_end = 0xb8000; 394 vga_vram_size = 0x8000;
395 display_desc = "EGA+"; 395 display_desc = "EGA+";
396 request_resource(&ioport_resource, 396 request_resource(&ioport_resource,
397 &ega_console_resource); 397 &ega_console_resource);
@@ -401,7 +401,7 @@ static const char __init *vgacon_startup(void)
401 static struct resource mda2_console_resource = 401 static struct resource mda2_console_resource =
402 { "mda", 0x3BF, 0x3BF }; 402 { "mda", 0x3BF, 0x3BF };
403 vga_video_type = VIDEO_TYPE_MDA; 403 vga_video_type = VIDEO_TYPE_MDA;
404 vga_vram_end = 0xb2000; 404 vga_vram_size = 0x2000;
405 display_desc = "*MDA"; 405 display_desc = "*MDA";
406 request_resource(&ioport_resource, 406 request_resource(&ioport_resource,
407 &mda1_console_resource); 407 &mda1_console_resource);
@@ -418,7 +418,7 @@ static const char __init *vgacon_startup(void)
418 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { 418 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
419 int i; 419 int i;
420 420
421 vga_vram_end = 0xc0000; 421 vga_vram_size = 0x8000;
422 422
423 if (!ORIG_VIDEO_ISVGA) { 423 if (!ORIG_VIDEO_ISVGA) {
424 static struct resource ega_console_resource 424 static struct resource ega_console_resource
@@ -443,7 +443,7 @@ static const char __init *vgacon_startup(void)
443 * and COE=1 isn't necessarily a good idea) 443 * and COE=1 isn't necessarily a good idea)
444 */ 444 */
445 vga_vram_base = 0xa0000; 445 vga_vram_base = 0xa0000;
446 vga_vram_end = 0xb0000; 446 vga_vram_size = 0x10000;
447 outb_p(6, VGA_GFX_I); 447 outb_p(6, VGA_GFX_I);
448 outb_p(6, VGA_GFX_D); 448 outb_p(6, VGA_GFX_D);
449#endif 449#endif
@@ -475,7 +475,7 @@ static const char __init *vgacon_startup(void)
475 static struct resource cga_console_resource = 475 static struct resource cga_console_resource =
476 { "cga", 0x3D4, 0x3D5 }; 476 { "cga", 0x3D4, 0x3D5 };
477 vga_video_type = VIDEO_TYPE_CGA; 477 vga_video_type = VIDEO_TYPE_CGA;
478 vga_vram_end = 0xba000; 478 vga_vram_size = 0x2000;
479 display_desc = "*CGA"; 479 display_desc = "*CGA";
480 request_resource(&ioport_resource, 480 request_resource(&ioport_resource,
481 &cga_console_resource); 481 &cga_console_resource);
@@ -483,9 +483,8 @@ static const char __init *vgacon_startup(void)
483 } 483 }
484 } 484 }
485 485
486 vga_vram_base = VGA_MAP_MEM(vga_vram_base); 486 vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
487 vga_vram_end = VGA_MAP_MEM(vga_vram_end); 487 vga_vram_end = vga_vram_base + vga_vram_size;
488 vga_vram_size = vga_vram_end - vga_vram_base;
489 488
490 /* 489 /*
491 * Find out if there is a graphics card present. 490 * Find out if there is a graphics card present.
@@ -1020,14 +1019,14 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
1020 char *charmap; 1019 char *charmap;
1021 1020
1022 if (vga_video_type != VIDEO_TYPE_EGAM) { 1021 if (vga_video_type != VIDEO_TYPE_EGAM) {
1023 charmap = (char *) VGA_MAP_MEM(colourmap); 1022 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
1024 beg = 0x0e; 1023 beg = 0x0e;
1025#ifdef VGA_CAN_DO_64KB 1024#ifdef VGA_CAN_DO_64KB
1026 if (vga_video_type == VIDEO_TYPE_VGAC) 1025 if (vga_video_type == VIDEO_TYPE_VGAC)
1027 beg = 0x06; 1026 beg = 0x06;
1028#endif 1027#endif
1029 } else { 1028 } else {
1030 charmap = (char *) VGA_MAP_MEM(blackwmap); 1029 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
1031 beg = 0x0a; 1030 beg = 0x0a;
1032 } 1031 }
1033 1032
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 34e07399756b..3ceb8c1b392e 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -18,6 +18,7 @@
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/fb.h> 19#include <linux/fb.h>
20#include <linux/console.h> 20#include <linux/console.h>
21#include <linux/module.h>
21 22
22/** 23/**
23 * framebuffer_alloc - creates a new frame buffer info structure 24 * framebuffer_alloc - creates a new frame buffer info structure
@@ -55,6 +56,10 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
55 56
56 info->device = dev; 57 info->device = dev;
57 58
59#ifdef CONFIG_FB_BACKLIGHT
60 mutex_init(&info->bl_mutex);
61#endif
62
58 return info; 63 return info;
59#undef PADDING 64#undef PADDING
60#undef BYTES_PER_LONG 65#undef BYTES_PER_LONG
@@ -414,6 +419,65 @@ static ssize_t show_fbstate(struct class_device *class_device, char *buf)
414 return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); 419 return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
415} 420}
416 421
422#ifdef CONFIG_FB_BACKLIGHT
423static ssize_t store_bl_curve(struct class_device *class_device,
424 const char *buf, size_t count)
425{
426 struct fb_info *fb_info = class_get_devdata(class_device);
427 u8 tmp_curve[FB_BACKLIGHT_LEVELS];
428 unsigned int i;
429
430 if (count != (FB_BACKLIGHT_LEVELS / 8 * 24))
431 return -EINVAL;
432
433 for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i)
434 if (sscanf(&buf[i * 24],
435 "%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n",
436 &tmp_curve[i * 8 + 0],
437 &tmp_curve[i * 8 + 1],
438 &tmp_curve[i * 8 + 2],
439 &tmp_curve[i * 8 + 3],
440 &tmp_curve[i * 8 + 4],
441 &tmp_curve[i * 8 + 5],
442 &tmp_curve[i * 8 + 6],
443 &tmp_curve[i * 8 + 7]) != 8)
444 return -EINVAL;
445
446 /* If there has been an error in the input data, we won't
447 * reach this loop.
448 */
449 mutex_lock(&fb_info->bl_mutex);
450 for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
451 fb_info->bl_curve[i] = tmp_curve[i];
452 mutex_unlock(&fb_info->bl_mutex);
453
454 return count;
455}
456
457static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
458{
459 struct fb_info *fb_info = class_get_devdata(class_device);
460 ssize_t len = 0;
461 unsigned int i;
462
463 mutex_lock(&fb_info->bl_mutex);
464 for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
465 len += snprintf(&buf[len], PAGE_SIZE,
466 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
467 fb_info->bl_curve[i + 0],
468 fb_info->bl_curve[i + 1],
469 fb_info->bl_curve[i + 2],
470 fb_info->bl_curve[i + 3],
471 fb_info->bl_curve[i + 4],
472 fb_info->bl_curve[i + 5],
473 fb_info->bl_curve[i + 6],
474 fb_info->bl_curve[i + 7]);
475 mutex_unlock(&fb_info->bl_mutex);
476
477 return len;
478}
479#endif
480
417/* When cmap is added back in it should be a binary attribute 481/* When cmap is added back in it should be a binary attribute
418 * not a text one. Consideration should also be given to converting 482 * not a text one. Consideration should also be given to converting
419 * fbdev to use configfs instead of sysfs */ 483 * fbdev to use configfs instead of sysfs */
@@ -432,6 +496,9 @@ static struct class_device_attribute class_device_attrs[] = {
432 __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), 496 __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate),
433 __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), 497 __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all),
434 __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), 498 __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
499#ifdef CONFIG_FB_BACKLIGHT
500 __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
501#endif
435}; 502};
436 503
437int fb_init_class_device(struct fb_info *fb_info) 504int fb_init_class_device(struct fb_info *fb_info)
@@ -454,4 +521,25 @@ void fb_cleanup_class_device(struct fb_info *fb_info)
454 &class_device_attrs[i]); 521 &class_device_attrs[i]);
455} 522}
456 523
524#ifdef CONFIG_FB_BACKLIGHT
525/* This function generates a linear backlight curve
526 *
527 * 0: off
528 * 1-7: min
529 * 8-127: linear from min to max
530 */
531void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
532{
533 unsigned int i, flat, count, range = (max - min);
534
535 fb_info->bl_curve[0] = off;
457 536
537 for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
538 fb_info->bl_curve[flat] = min;
539
540 count = FB_BACKLIGHT_LEVELS * 15 / 16;
541 for (i = 0; i < count; ++i)
542 fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
543}
544EXPORT_SYMBOL_GPL(fb_bl_default_curve);
545#endif
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 6b88050d21bf..8a0c2d3d3805 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -232,9 +232,6 @@ static int igafb_mmap(struct fb_info *info,
232 232
233 size = vma->vm_end - vma->vm_start; 233 size = vma->vm_end - vma->vm_start;
234 234
235 /* To stop the swapper from even considering these pages. */
236 vma->vm_flags |= (VM_SHM | VM_LOCKED);
237
238 /* Each page, see which map applies */ 235 /* Each page, see which map applies */
239 for (page = 0; page < size; ) { 236 for (page = 0; page < size; ) {
240 map_size = 0; 237 map_size = 0;
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index da29d007f215..e290d7460e1b 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -8,9 +8,9 @@
8 8
9 9
10/*** Version/name ***/ 10/*** Version/name ***/
11#define INTELFB_VERSION "0.9.2" 11#define INTELFB_VERSION "0.9.4"
12#define INTELFB_MODULE_NAME "intelfb" 12#define INTELFB_MODULE_NAME "intelfb"
13#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM" 13#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM"
14 14
15 15
16/*** Debug/feature defines ***/ 16/*** Debug/feature defines ***/
@@ -52,11 +52,14 @@
52#define PCI_DEVICE_ID_INTEL_865G 0x2572 52#define PCI_DEVICE_ID_INTEL_865G 0x2572
53#define PCI_DEVICE_ID_INTEL_915G 0x2582 53#define PCI_DEVICE_ID_INTEL_915G 0x2582
54#define PCI_DEVICE_ID_INTEL_915GM 0x2592 54#define PCI_DEVICE_ID_INTEL_915GM 0x2592
55#define PCI_DEVICE_ID_INTEL_945G 0x2772
56#define PCI_DEVICE_ID_INTEL_945GM 0x27A2
55 57
56/* Size of MMIO region */ 58/* Size of MMIO region */
57#define INTEL_REG_SIZE 0x80000 59#define INTEL_REG_SIZE 0x80000
58 60
59#define STRIDE_ALIGNMENT 16 61#define STRIDE_ALIGNMENT 16
62#define STRIDE_ALIGNMENT_I9XX 64
60 63
61#define PALETTE_8_ENTRIES 256 64#define PALETTE_8_ENTRIES 256
62 65
@@ -125,7 +128,9 @@ enum intel_chips {
125 INTEL_855GME, 128 INTEL_855GME,
126 INTEL_865G, 129 INTEL_865G,
127 INTEL_915G, 130 INTEL_915G,
128 INTEL_915GM 131 INTEL_915GM,
132 INTEL_945G,
133 INTEL_945GM,
129}; 134};
130 135
131struct intelfb_hwstate { 136struct intelfb_hwstate {
@@ -232,7 +237,7 @@ struct intelfb_info {
232 u32 fb_start; 237 u32 fb_start;
233 238
234 /* ring buffer */ 239 /* ring buffer */
235 u8 __iomem *ring_head; 240 u32 ring_head;
236 u32 ring_tail; 241 u32 ring_tail;
237 u32 ring_tail_mask; 242 u32 ring_tail_mask;
238 u32 ring_space; 243 u32 ring_space;
@@ -277,8 +282,13 @@ struct intelfb_info {
277 282
278 /* driver registered */ 283 /* driver registered */
279 int registered; 284 int registered;
285
286 /* index into plls */
287 int pll_index;
280}; 288};
281 289
290#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM))
291
282/*** function prototypes ***/ 292/*** function prototypes ***/
283 293
284extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); 294extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 995b47c165a7..0a0a8b199ecc 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1,11 +1,12 @@
1/* 1/*
2 * intelfb 2 * intelfb
3 * 3 *
4 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM 4 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
5 * integrated graphics chips. 5 * 945G/945GM integrated graphics chips.
6 * 6 *
7 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> 7 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
8 * 2004 Sylvain Meyer 8 * 2004 Sylvain Meyer
9 * 2006 David Airlie
9 * 10 *
10 * This driver consists of two parts. The first part (intelfbdrv.c) provides 11 * This driver consists of two parts. The first part (intelfbdrv.c) provides
11 * the basic fbdev interfaces, is derived in part from the radeonfb and 12 * the basic fbdev interfaces, is derived in part from the radeonfb and
@@ -131,6 +132,7 @@
131 132
132#include "intelfb.h" 133#include "intelfb.h"
133#include "intelfbhw.h" 134#include "intelfbhw.h"
135#include "../edid.h"
134 136
135static void __devinit get_initial_mode(struct intelfb_info *dinfo); 137static void __devinit get_initial_mode(struct intelfb_info *dinfo);
136static void update_dinfo(struct intelfb_info *dinfo, 138static void update_dinfo(struct intelfb_info *dinfo,
@@ -182,6 +184,8 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
182 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G }, 184 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
183 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G }, 185 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
184 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM }, 186 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
187 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
188 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
185 { 0, } 189 { 0, }
186}; 190};
187 191
@@ -261,7 +265,7 @@ MODULE_PARM_DESC(mode,
261 265
262#ifndef MODULE 266#ifndef MODULE
263#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name))) 267#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
264#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0) 268#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
265#define OPT_STRVAL(opt, name) (opt + strlen(name)) 269#define OPT_STRVAL(opt, name) (opt + strlen(name))
266 270
267static __inline__ char * 271static __inline__ char *
@@ -546,11 +550,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
546 550
547 /* Set base addresses. */ 551 /* Set base addresses. */
548 if ((ent->device == PCI_DEVICE_ID_INTEL_915G) || 552 if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
549 (ent->device == PCI_DEVICE_ID_INTEL_915GM)) { 553 (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
554 (ent->device == PCI_DEVICE_ID_INTEL_945G) ||
555 (ent->device == PCI_DEVICE_ID_INTEL_945GM)) {
550 aperture_bar = 2; 556 aperture_bar = 2;
551 mmio_bar = 0; 557 mmio_bar = 0;
552 /* Disable HW cursor on 915G/M (not implemented yet) */
553 hwcursor = 0;
554 } 558 }
555 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar); 559 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
556 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar); 560 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar);
@@ -584,8 +588,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
584 /* Get the chipset info. */ 588 /* Get the chipset info. */
585 dinfo->pci_chipset = pdev->device; 589 dinfo->pci_chipset = pdev->device;
586 590
587 if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset, 591 if (intelfbhw_get_chipset(pdev, dinfo)) {
588 &dinfo->mobile)) {
589 cleanup(dinfo); 592 cleanup(dinfo);
590 return -ENODEV; 593 return -ENODEV;
591 } 594 }
@@ -704,7 +707,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
704 + (dinfo->ring.offset << 12); 707 + (dinfo->ring.offset << 12);
705 dinfo->ring.virtual = dinfo->aperture.virtual 708 dinfo->ring.virtual = dinfo->aperture.virtual
706 + (dinfo->ring.offset << 12); 709 + (dinfo->ring.offset << 12);
707 dinfo->ring_head = dinfo->ring.virtual; 710 dinfo->ring_head = 0;
708 } 711 }
709 if (dinfo->hwcursor) { 712 if (dinfo->hwcursor) {
710 agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY 713 agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
@@ -763,18 +766,18 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
763 if (mtrr) 766 if (mtrr)
764 set_mtrr(dinfo); 767 set_mtrr(dinfo);
765 768
766 DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%x)\n", 769 DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
767 dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size, 770 dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
768 (u32 __iomem ) dinfo->fb.virtual); 771 dinfo->fb.virtual);
769 DBG_MSG("MMIO: 0x%x/0x%x (0x%x)\n", 772 DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
770 dinfo->mmio_base_phys, INTEL_REG_SIZE, 773 dinfo->mmio_base_phys, INTEL_REG_SIZE,
771 (u32 __iomem) dinfo->mmio_base); 774 dinfo->mmio_base);
772 DBG_MSG("ring buffer: 0x%x/0x%x (0x%x)\n", 775 DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
773 dinfo->ring.physical, dinfo->ring.size, 776 dinfo->ring.physical, dinfo->ring.size,
774 (u32 __iomem ) dinfo->ring.virtual); 777 dinfo->ring.virtual);
775 DBG_MSG("HW cursor: 0x%x/0x%x (0x%x) (offset 0x%x) (phys 0x%x)\n", 778 DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
776 dinfo->cursor.physical, dinfo->cursor.size, 779 dinfo->cursor.physical, dinfo->cursor.size,
777 (u32 __iomem ) dinfo->cursor.virtual, dinfo->cursor.offset, 780 dinfo->cursor.virtual, dinfo->cursor.offset,
778 dinfo->cursor.physical); 781 dinfo->cursor.physical);
779 782
780 DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, " 783 DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
@@ -1029,17 +1032,44 @@ intelfb_init_var(struct intelfb_info *dinfo)
1029 sizeof(struct fb_var_screeninfo)); 1032 sizeof(struct fb_var_screeninfo));
1030 msrc = 5; 1033 msrc = 5;
1031 } else { 1034 } else {
1035 const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
1036 u8 *edid_d = NULL;
1037
1038 if (edid_s) {
1039 edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL);
1040
1041 if (edid_d) {
1042 memcpy(edid_d, edid_s, EDID_LENGTH);
1043 fb_edid_to_monspecs(edid_d,
1044 &dinfo->info->monspecs);
1045 kfree(edid_d);
1046 }
1047 }
1048
1032 if (mode) { 1049 if (mode) {
1050 printk("intelfb: Looking for mode in private "
1051 "database\n");
1033 msrc = fb_find_mode(var, dinfo->info, mode, 1052 msrc = fb_find_mode(var, dinfo->info, mode,
1034 vesa_modes, VESA_MODEDB_SIZE, 1053 dinfo->info->monspecs.modedb,
1054 dinfo->info->monspecs.modedb_len,
1035 NULL, 0); 1055 NULL, 0);
1036 if (msrc) 1056
1037 msrc |= 8; 1057 if (msrc && msrc > 1) {
1058 printk("intelfb: No mode in private database, "
1059 "intelfb: looking for mode in global "
1060 "database ");
1061 msrc = fb_find_mode(var, dinfo->info, mode,
1062 NULL, 0, NULL, 0);
1063
1064 if (msrc)
1065 msrc |= 8;
1066 }
1067
1038 } 1068 }
1069
1039 if (!msrc) { 1070 if (!msrc) {
1040 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE, 1071 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
1041 vesa_modes, VESA_MODEDB_SIZE, 1072 NULL, 0, NULL, 0);
1042 NULL, 0);
1043 } 1073 }
1044 } 1074 }
1045 1075
@@ -1139,7 +1169,10 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
1139 } 1169 }
1140 1170
1141 /* Make sure the line length is a aligned correctly. */ 1171 /* Make sure the line length is a aligned correctly. */
1142 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT); 1172 if (IS_I9XX(dinfo))
1173 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
1174 else
1175 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
1143 1176
1144 if (FIXED_MODE(dinfo)) 1177 if (FIXED_MODE(dinfo))
1145 dinfo->pitch = dinfo->initial_pitch; 1178 dinfo->pitch = dinfo->initial_pitch;
@@ -1162,16 +1195,33 @@ intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1162 struct fb_var_screeninfo v; 1195 struct fb_var_screeninfo v;
1163 struct intelfb_info *dinfo; 1196 struct intelfb_info *dinfo;
1164 static int first = 1; 1197 static int first = 1;
1198 int i;
1199 /* Good pitches to allow tiling. Don't care about pitches < 1024. */
1200 static const int pitches[] = {
1201 128 * 8,
1202 128 * 16,
1203 128 * 32,
1204 128 * 64,
1205 0
1206 };
1165 1207
1166 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags); 1208 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
1167 1209
1168 dinfo = GET_DINFO(info); 1210 dinfo = GET_DINFO(info);
1169 1211
1212 /* update the pitch */
1170 if (intelfbhw_validate_mode(dinfo, var) != 0) 1213 if (intelfbhw_validate_mode(dinfo, var) != 0)
1171 return -EINVAL; 1214 return -EINVAL;
1172 1215
1173 v = *var; 1216 v = *var;
1174 1217
1218 for (i = 0; pitches[i] != 0; i++) {
1219 if (pitches[i] >= v.xres_virtual) {
1220 v.xres_virtual = pitches[i];
1221 break;
1222 }
1223 }
1224
1175 /* Check for a supported bpp. */ 1225 /* Check for a supported bpp. */
1176 if (v.bits_per_pixel <= 8) { 1226 if (v.bits_per_pixel <= 8) {
1177 v.bits_per_pixel = 8; 1227 v.bits_per_pixel = 8;
@@ -1467,7 +1517,7 @@ static int
1467intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) 1517intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1468{ 1518{
1469 struct intelfb_info *dinfo = GET_DINFO(info); 1519 struct intelfb_info *dinfo = GET_DINFO(info);
1470 1520 u32 physical;
1471#if VERBOSE > 0 1521#if VERBOSE > 0
1472 DBG_MSG("intelfb_cursor\n"); 1522 DBG_MSG("intelfb_cursor\n");
1473#endif 1523#endif
@@ -1478,7 +1528,10 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1478 intelfbhw_cursor_hide(dinfo); 1528 intelfbhw_cursor_hide(dinfo);
1479 1529
1480 /* If XFree killed the cursor - restore it */ 1530 /* If XFree killed the cursor - restore it */
1481 if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) { 1531 physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
1532 (dinfo->cursor.offset << 12);
1533
1534 if (INREG(CURSOR_A_BASEADDR) != physical) {
1482 u32 fg, bg; 1535 u32 fg, bg;
1483 1536
1484 DBG_MSG("the cursor was killed - restore it !!\n"); 1537 DBG_MSG("the cursor was killed - restore it !!\n");
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 624c4bc96f0d..7533b3dd08ac 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -40,68 +40,110 @@
40#include "intelfb.h" 40#include "intelfb.h"
41#include "intelfbhw.h" 41#include "intelfbhw.h"
42 42
43struct pll_min_max {
44 int min_m, max_m, min_m1, max_m1;
45 int min_m2, max_m2, min_n, max_n;
46 int min_p, max_p, min_p1, max_p1;
47 int min_vco, max_vco, p_transition_clk, ref_clk;
48 int p_inc_lo, p_inc_hi;
49};
50
51#define PLLS_I8xx 0
52#define PLLS_I9xx 1
53#define PLLS_MAX 2
54
55static struct pll_min_max plls[PLLS_MAX] = {
56 { 108, 140, 18, 26,
57 6, 16, 3, 16,
58 4, 128, 0, 31,
59 930000, 1400000, 165000, 48000,
60 4, 2 }, //I8xx
61
62 { 75, 120, 10, 20,
63 5, 9, 4, 7,
64 5, 80, 1, 8,
65 1400000, 2800000, 200000, 96000,
66 10, 5 } //I9xx
67};
68
43int 69int
44intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, 70intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
45 int *mobile)
46{ 71{
47 u32 tmp; 72 u32 tmp;
48 73 if (!pdev || !dinfo)
49 if (!pdev || !name || !chipset || !mobile)
50 return 1; 74 return 1;
51 75
52 switch (pdev->device) { 76 switch (pdev->device) {
53 case PCI_DEVICE_ID_INTEL_830M: 77 case PCI_DEVICE_ID_INTEL_830M:
54 *name = "Intel(R) 830M"; 78 dinfo->name = "Intel(R) 830M";
55 *chipset = INTEL_830M; 79 dinfo->chipset = INTEL_830M;
56 *mobile = 1; 80 dinfo->mobile = 1;
81 dinfo->pll_index = PLLS_I8xx;
57 return 0; 82 return 0;
58 case PCI_DEVICE_ID_INTEL_845G: 83 case PCI_DEVICE_ID_INTEL_845G:
59 *name = "Intel(R) 845G"; 84 dinfo->name = "Intel(R) 845G";
60 *chipset = INTEL_845G; 85 dinfo->chipset = INTEL_845G;
61 *mobile = 0; 86 dinfo->mobile = 0;
87 dinfo->pll_index = PLLS_I8xx;
62 return 0; 88 return 0;
63 case PCI_DEVICE_ID_INTEL_85XGM: 89 case PCI_DEVICE_ID_INTEL_85XGM:
64 tmp = 0; 90 tmp = 0;
65 *mobile = 1; 91 dinfo->mobile = 1;
92 dinfo->pll_index = PLLS_I8xx;
66 pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp); 93 pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
67 switch ((tmp >> INTEL_85X_VARIANT_SHIFT) & 94 switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
68 INTEL_85X_VARIANT_MASK) { 95 INTEL_85X_VARIANT_MASK) {
69 case INTEL_VAR_855GME: 96 case INTEL_VAR_855GME:
70 *name = "Intel(R) 855GME"; 97 dinfo->name = "Intel(R) 855GME";
71 *chipset = INTEL_855GME; 98 dinfo->chipset = INTEL_855GME;
72 return 0; 99 return 0;
73 case INTEL_VAR_855GM: 100 case INTEL_VAR_855GM:
74 *name = "Intel(R) 855GM"; 101 dinfo->name = "Intel(R) 855GM";
75 *chipset = INTEL_855GM; 102 dinfo->chipset = INTEL_855GM;
76 return 0; 103 return 0;
77 case INTEL_VAR_852GME: 104 case INTEL_VAR_852GME:
78 *name = "Intel(R) 852GME"; 105 dinfo->name = "Intel(R) 852GME";
79 *chipset = INTEL_852GME; 106 dinfo->chipset = INTEL_852GME;
80 return 0; 107 return 0;
81 case INTEL_VAR_852GM: 108 case INTEL_VAR_852GM:
82 *name = "Intel(R) 852GM"; 109 dinfo->name = "Intel(R) 852GM";
83 *chipset = INTEL_852GM; 110 dinfo->chipset = INTEL_852GM;
84 return 0; 111 return 0;
85 default: 112 default:
86 *name = "Intel(R) 852GM/855GM"; 113 dinfo->name = "Intel(R) 852GM/855GM";
87 *chipset = INTEL_85XGM; 114 dinfo->chipset = INTEL_85XGM;
88 return 0; 115 return 0;
89 } 116 }
90 break; 117 break;
91 case PCI_DEVICE_ID_INTEL_865G: 118 case PCI_DEVICE_ID_INTEL_865G:
92 *name = "Intel(R) 865G"; 119 dinfo->name = "Intel(R) 865G";
93 *chipset = INTEL_865G; 120 dinfo->chipset = INTEL_865G;
94 *mobile = 0; 121 dinfo->mobile = 0;
122 dinfo->pll_index = PLLS_I8xx;
95 return 0; 123 return 0;
96 case PCI_DEVICE_ID_INTEL_915G: 124 case PCI_DEVICE_ID_INTEL_915G:
97 *name = "Intel(R) 915G"; 125 dinfo->name = "Intel(R) 915G";
98 *chipset = INTEL_915G; 126 dinfo->chipset = INTEL_915G;
99 *mobile = 0; 127 dinfo->mobile = 0;
128 dinfo->pll_index = PLLS_I9xx;
100 return 0; 129 return 0;
101 case PCI_DEVICE_ID_INTEL_915GM: 130 case PCI_DEVICE_ID_INTEL_915GM:
102 *name = "Intel(R) 915GM"; 131 dinfo->name = "Intel(R) 915GM";
103 *chipset = INTEL_915GM; 132 dinfo->chipset = INTEL_915GM;
104 *mobile = 1; 133 dinfo->mobile = 1;
134 dinfo->pll_index = PLLS_I9xx;
135 return 0;
136 case PCI_DEVICE_ID_INTEL_945G:
137 dinfo->name = "Intel(R) 945G";
138 dinfo->chipset = INTEL_945G;
139 dinfo->mobile = 0;
140 dinfo->pll_index = PLLS_I9xx;
141 return 0;
142 case PCI_DEVICE_ID_INTEL_945GM:
143 dinfo->name = "Intel(R) 945GM";
144 dinfo->chipset = INTEL_945GM;
145 dinfo->mobile = 1;
146 dinfo->pll_index = PLLS_I9xx;
105 return 0; 147 return 0;
106 default: 148 default:
107 return 1; 149 return 1;
@@ -114,6 +156,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
114{ 156{
115 struct pci_dev *bridge_dev; 157 struct pci_dev *bridge_dev;
116 u16 tmp; 158 u16 tmp;
159 int stolen_overhead;
117 160
118 if (!pdev || !aperture_size || !stolen_size) 161 if (!pdev || !aperture_size || !stolen_size)
119 return 1; 162 return 1;
@@ -128,21 +171,41 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
128 tmp = 0; 171 tmp = 0;
129 pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); 172 pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
130 switch (pdev->device) { 173 switch (pdev->device) {
131 case PCI_DEVICE_ID_INTEL_830M: 174 case PCI_DEVICE_ID_INTEL_915G:
132 case PCI_DEVICE_ID_INTEL_845G: 175 case PCI_DEVICE_ID_INTEL_915GM:
176 case PCI_DEVICE_ID_INTEL_945G:
177 case PCI_DEVICE_ID_INTEL_945GM:
178 /* 915 and 945 chipsets support a 256MB aperture.
179 Aperture size is determined by inspected the
180 base address of the aperture. */
181 if (pci_resource_start(pdev, 2) & 0x08000000)
182 *aperture_size = MB(128);
183 else
184 *aperture_size = MB(256);
185 break;
186 default:
133 if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) 187 if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
134 *aperture_size = MB(64); 188 *aperture_size = MB(64);
135 else 189 else
136 *aperture_size = MB(128); 190 *aperture_size = MB(128);
191 break;
192 }
193
194 /* Stolen memory size is reduced by the GTT and the popup.
195 GTT is 1K per MB of aperture size, and popup is 4K. */
196 stolen_overhead = (*aperture_size / MB(1)) + 4;
197 switch(pdev->device) {
198 case PCI_DEVICE_ID_INTEL_830M:
199 case PCI_DEVICE_ID_INTEL_845G:
137 switch (tmp & INTEL_830_GMCH_GMS_MASK) { 200 switch (tmp & INTEL_830_GMCH_GMS_MASK) {
138 case INTEL_830_GMCH_GMS_STOLEN_512: 201 case INTEL_830_GMCH_GMS_STOLEN_512:
139 *stolen_size = KB(512) - KB(132); 202 *stolen_size = KB(512) - KB(stolen_overhead);
140 return 0; 203 return 0;
141 case INTEL_830_GMCH_GMS_STOLEN_1024: 204 case INTEL_830_GMCH_GMS_STOLEN_1024:
142 *stolen_size = MB(1) - KB(132); 205 *stolen_size = MB(1) - KB(stolen_overhead);
143 return 0; 206 return 0;
144 case INTEL_830_GMCH_GMS_STOLEN_8192: 207 case INTEL_830_GMCH_GMS_STOLEN_8192:
145 *stolen_size = MB(8) - KB(132); 208 *stolen_size = MB(8) - KB(stolen_overhead);
146 return 0; 209 return 0;
147 case INTEL_830_GMCH_GMS_LOCAL: 210 case INTEL_830_GMCH_GMS_LOCAL:
148 ERR_MSG("only local memory found\n"); 211 ERR_MSG("only local memory found\n");
@@ -157,28 +220,27 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
157 } 220 }
158 break; 221 break;
159 default: 222 default:
160 *aperture_size = MB(128);
161 switch (tmp & INTEL_855_GMCH_GMS_MASK) { 223 switch (tmp & INTEL_855_GMCH_GMS_MASK) {
162 case INTEL_855_GMCH_GMS_STOLEN_1M: 224 case INTEL_855_GMCH_GMS_STOLEN_1M:
163 *stolen_size = MB(1) - KB(132); 225 *stolen_size = MB(1) - KB(stolen_overhead);
164 return 0; 226 return 0;
165 case INTEL_855_GMCH_GMS_STOLEN_4M: 227 case INTEL_855_GMCH_GMS_STOLEN_4M:
166 *stolen_size = MB(4) - KB(132); 228 *stolen_size = MB(4) - KB(stolen_overhead);
167 return 0; 229 return 0;
168 case INTEL_855_GMCH_GMS_STOLEN_8M: 230 case INTEL_855_GMCH_GMS_STOLEN_8M:
169 *stolen_size = MB(8) - KB(132); 231 *stolen_size = MB(8) - KB(stolen_overhead);
170 return 0; 232 return 0;
171 case INTEL_855_GMCH_GMS_STOLEN_16M: 233 case INTEL_855_GMCH_GMS_STOLEN_16M:
172 *stolen_size = MB(16) - KB(132); 234 *stolen_size = MB(16) - KB(stolen_overhead);
173 return 0; 235 return 0;
174 case INTEL_855_GMCH_GMS_STOLEN_32M: 236 case INTEL_855_GMCH_GMS_STOLEN_32M:
175 *stolen_size = MB(32) - KB(132); 237 *stolen_size = MB(32) - KB(stolen_overhead);
176 return 0; 238 return 0;
177 case INTEL_915G_GMCH_GMS_STOLEN_48M: 239 case INTEL_915G_GMCH_GMS_STOLEN_48M:
178 *stolen_size = MB(48) - KB(132); 240 *stolen_size = MB(48) - KB(stolen_overhead);
179 return 0; 241 return 0;
180 case INTEL_915G_GMCH_GMS_STOLEN_64M: 242 case INTEL_915G_GMCH_GMS_STOLEN_64M:
181 *stolen_size = MB(64) - KB(132); 243 *stolen_size = MB(64) - KB(stolen_overhead);
182 return 0; 244 return 0;
183 case INTEL_855_GMCH_GMS_DISABLED: 245 case INTEL_855_GMCH_GMS_DISABLED:
184 ERR_MSG("video memory is disabled\n"); 246 ERR_MSG("video memory is disabled\n");
@@ -529,12 +591,63 @@ intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
529} 591}
530 592
531 593
594static int calc_vclock3(int index, int m, int n, int p)
595{
596 if (p == 0 || n == 0)
597 return 0;
598 return plls[index].ref_clk * m / n / p;
599}
600
601static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds)
602{
603 struct pll_min_max *pll = &plls[index];
604 u32 m, vco, p;
605
606 m = (5 * (m1 + 2)) + (m2 + 2);
607 n += 2;
608 vco = pll->ref_clk * m / n;
609
610 if (index == PLLS_I8xx) {
611 p = ((p1 + 2) * (1 << (p2 + 1)));
612 } else {
613 p = ((p1) * (p2 ? 5 : 10));
614 }
615 return vco / p;
616}
617
618static void
619intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
620{
621 int p1, p2;
622
623 if (IS_I9XX(dinfo)) {
624 if (dpll & DPLL_P1_FORCE_DIV2)
625 p1 = 1;
626 else
627 p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
628
629 p1 = ffs(p1);
630
631 p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
632 } else {
633 if (dpll & DPLL_P1_FORCE_DIV2)
634 p1 = 0;
635 else
636 p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
637 p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
638 }
639
640 *o_p1 = p1;
641 *o_p2 = p2;
642}
643
644
532void 645void
533intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) 646intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
534{ 647{
535#if REGDUMP 648#if REGDUMP
536 int i, m1, m2, n, p1, p2; 649 int i, m1, m2, n, p1, p2;
537 650 int index = dinfo->pll_index;
538 DBG_MSG("intelfbhw_print_hw_state\n"); 651 DBG_MSG("intelfbhw_print_hw_state\n");
539 652
540 if (!hw || !dinfo) 653 if (!hw || !dinfo)
@@ -547,26 +660,22 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
547 n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 660 n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
548 m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 661 m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
549 m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 662 m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
550 if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2) 663
551 p1 = 0; 664 intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
552 else 665
553 p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;
554 p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;
555 printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", 666 printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
556 m1, m2, n, p1, p2); 667 m1, m2, n, p1, p2);
557 printk(" VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); 668 printk(" VGA0: clock is %d\n",
669 calc_vclock(index, m1, m2, n, p1, p2, 0));
558 670
559 n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 671 n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
560 m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 672 m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
561 m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 673 m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
562 if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2) 674
563 p1 = 0; 675 intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
564 else
565 p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;
566 p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;
567 printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", 676 printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
568 m1, m2, n, p1, p2); 677 m1, m2, n, p1, p2);
569 printk(" VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); 678 printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
570 679
571 printk(" DPLL_A: 0x%08x\n", hw->dpll_a); 680 printk(" DPLL_A: 0x%08x\n", hw->dpll_a);
572 printk(" DPLL_B: 0x%08x\n", hw->dpll_b); 681 printk(" DPLL_B: 0x%08x\n", hw->dpll_b);
@@ -578,34 +687,30 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
578 n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 687 n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
579 m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 688 m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
580 m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 689 m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
581 if (hw->dpll_a & DPLL_P1_FORCE_DIV2) 690
582 p1 = 0; 691 intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
583 else 692
584 p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
585 p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
586 printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", 693 printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
587 m1, m2, n, p1, p2); 694 m1, m2, n, p1, p2);
588 printk(" PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); 695 printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
589 696
590 n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 697 n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
591 m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 698 m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
592 m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; 699 m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
593 if (hw->dpll_a & DPLL_P1_FORCE_DIV2) 700
594 p1 = 0; 701 intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
595 else 702
596 p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
597 p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
598 printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", 703 printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
599 m1, m2, n, p1, p2); 704 m1, m2, n, p1, p2);
600 printk(" PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); 705 printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
601 706
602#if 0 707#if 0
603 printk(" PALETTE_A:\n"); 708 printk(" PALETTE_A:\n");
604 for (i = 0; i < PALETTE_8_ENTRIES) 709 for (i = 0; i < PALETTE_8_ENTRIES)
605 printk(" %3d: 0x%08x\n", i, hw->palette_a[i]; 710 printk(" %3d: 0x%08x\n", i, hw->palette_a[i]);
606 printk(" PALETTE_B:\n"); 711 printk(" PALETTE_B:\n");
607 for (i = 0; i < PALETTE_8_ENTRIES) 712 for (i = 0; i < PALETTE_8_ENTRIES)
608 printk(" %3d: 0x%08x\n", i, hw->palette_b[i]; 713 printk(" %3d: 0x%08x\n", i, hw->palette_b[i]);
609#endif 714#endif
610 715
611 printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a); 716 printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a);
@@ -680,11 +785,11 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
680 } 785 }
681 for (i = 0; i < 3; i++) { 786 for (i = 0; i < 3; i++) {
682 printk(" SWF3%d 0x%08x\n", i, 787 printk(" SWF3%d 0x%08x\n", i,
683 hw->swf3x[i]); 788 hw->swf3x[i]);
684 } 789 }
685 for (i = 0; i < 8; i++) 790 for (i = 0; i < 8; i++)
686 printk(" FENCE%d 0x%08x\n", i, 791 printk(" FENCE%d 0x%08x\n", i,
687 hw->fence[i]); 792 hw->fence[i]);
688 793
689 printk(" INSTPM 0x%08x\n", hw->instpm); 794 printk(" INSTPM 0x%08x\n", hw->instpm);
690 printk(" MEM_MODE 0x%08x\n", hw->mem_mode); 795 printk(" MEM_MODE 0x%08x\n", hw->mem_mode);
@@ -695,43 +800,58 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
695#endif 800#endif
696} 801}
697 802
803
804
698/* Split the M parameter into M1 and M2. */ 805/* Split the M parameter into M1 and M2. */
699static int 806static int
700splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2) 807splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2)
701{ 808{
702 int m1, m2; 809 int m1, m2;
703 810 int testm;
704 m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2; 811 struct pll_min_max *pll = &plls[index];
705 if (m1 < MIN_M1) 812
706 m1 = MIN_M1; 813 /* no point optimising too much - brute force m */
707 if (m1 > MAX_M1) 814 for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
708 m1 = MAX_M1; 815 for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
709 m2 = m - 5 * (m1 + 2) - 2; 816 testm = (5 * (m1 + 2)) + (m2 + 2);
710 if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) { 817 if (testm == m) {
711 return 1; 818 *retm1 = (unsigned int)m1;
712 } else { 819 *retm2 = (unsigned int)m2;
713 *retm1 = (unsigned int)m1; 820 return 0;
714 *retm2 = (unsigned int)m2; 821 }
715 return 0; 822 }
716 } 823 }
824 return 1;
717} 825}
718 826
719/* Split the P parameter into P1 and P2. */ 827/* Split the P parameter into P1 and P2. */
720static int 828static int
721splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) 829splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2)
722{ 830{
723 int p1, p2; 831 int p1, p2;
832 struct pll_min_max *pll = &plls[index];
833
834 if (index == PLLS_I9xx) {
835 p2 = (p % 10) ? 1 : 0;
836
837 p1 = p / (p2 ? 5 : 10);
838
839 *retp1 = (unsigned int)p1;
840 *retp2 = (unsigned int)p2;
841 return 0;
842 }
724 843
725 if (p % 4 == 0) 844 if (p % 4 == 0)
726 p2 = 1; 845 p2 = 1;
727 else 846 else
728 p2 = 0; 847 p2 = 0;
729 p1 = (p / (1 << (p2 + 1))) - 2; 848 p1 = (p / (1 << (p2 + 1))) - 2;
730 if (p % 4 == 0 && p1 < MIN_P1) { 849 if (p % 4 == 0 && p1 < pll->min_p1) {
731 p2 = 0; 850 p2 = 0;
732 p1 = (p / (1 << (p2 + 1))) - 2; 851 p1 = (p / (1 << (p2 + 1))) - 2;
733 } 852 }
734 if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) { 853 if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
854 (p1 + 2) * (1 << (p2 + 1)) != p) {
735 return 1; 855 return 1;
736 } else { 856 } else {
737 *retp1 = (unsigned int)p1; 857 *retp1 = (unsigned int)p1;
@@ -741,14 +861,15 @@ splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
741} 861}
742 862
743static int 863static int
744calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, 864calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
745 u32 *retp2, u32 *retclock) 865 u32 *retp2, u32 *retclock)
746{ 866{
747 u32 m1, m2, n, p1, p2, n1; 867 u32 m1, m2, n, p1, p2, n1, testm;
748 u32 f_vco, p, p_best = 0, m, f_out; 868 u32 f_vco, p, p_best = 0, m, f_out = 0;
749 u32 err_max, err_target, err_best = 10000000; 869 u32 err_max, err_target, err_best = 10000000;
750 u32 n_best = 0, m_best = 0, f_best, f_err; 870 u32 n_best = 0, m_best = 0, f_best, f_err;
751 u32 p_min, p_max, p_inc, div_min, div_max; 871 u32 p_min, p_max, p_inc, div_max;
872 struct pll_min_max *pll = &plls[index];
752 873
753 /* Accept 0.5% difference, but aim for 0.1% */ 874 /* Accept 0.5% difference, but aim for 0.1% */
754 err_max = 5 * clock / 1000; 875 err_max = 5 * clock / 1000;
@@ -756,58 +877,56 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
756 877
757 DBG_MSG("Clock is %d\n", clock); 878 DBG_MSG("Clock is %d\n", clock);
758 879
759 div_max = MAX_VCO_FREQ / clock; 880 div_max = pll->max_vco / clock;
760 div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
761 881
762 if (clock <= P_TRANSITION_CLOCK) 882 p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
763 p_inc = 4; 883 p_min = p_inc;
764 else
765 p_inc = 2;
766 p_min = ROUND_UP_TO(div_min, p_inc);
767 p_max = ROUND_DOWN_TO(div_max, p_inc); 884 p_max = ROUND_DOWN_TO(div_max, p_inc);
768 if (p_min < MIN_P) 885 if (p_min < pll->min_p)
769 p_min = 4; 886 p_min = pll->min_p;
770 if (p_max > MAX_P) 887 if (p_max > pll->max_p)
771 p_max = 128; 888 p_max = pll->max_p;
772 889
773 DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); 890 DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
774 891
775 p = p_min; 892 p = p_min;
776 do { 893 do {
777 if (splitp(p, &p1, &p2)) { 894 if (splitp(index, p, &p1, &p2)) {
778 WRN_MSG("cannot split p = %d\n", p); 895 WRN_MSG("cannot split p = %d\n", p);
779 p += p_inc; 896 p += p_inc;
780 continue; 897 continue;
781 } 898 }
782 n = MIN_N; 899 n = pll->min_n;
783 f_vco = clock * p; 900 f_vco = clock * p;
784 901
785 do { 902 do {
786 m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; 903 m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
787 if (m < MIN_M) 904 if (m < pll->min_m)
788 m = MIN_M; 905 m = pll->min_m + 1;
789 if (m > MAX_M) 906 if (m > pll->max_m)
790 m = MAX_M; 907 m = pll->max_m - 1;
791 f_out = CALC_VCLOCK3(m, n, p); 908 for (testm = m - 1; testm <= m; testm++) {
792 if (splitm(m, &m1, &m2)) { 909 f_out = calc_vclock3(index, m, n, p);
793 WRN_MSG("cannot split m = %d\n", m); 910 if (splitm(index, testm, &m1, &m2)) {
794 n++; 911 WRN_MSG("cannot split m = %d\n", m);
795 continue; 912 n++;
796 } 913 continue;
797 if (clock > f_out) 914 }
798 f_err = clock - f_out; 915 if (clock > f_out)
799 else 916 f_err = clock - f_out;
800 f_err = f_out - clock; 917 else/* slightly bias the error for bigger clocks */
801 918 f_err = f_out - clock + 1;
802 if (f_err < err_best) { 919
803 m_best = m; 920 if (f_err < err_best) {
804 n_best = n; 921 m_best = testm;
805 p_best = p; 922 n_best = n;
806 f_best = f_out; 923 p_best = p;
807 err_best = f_err; 924 f_best = f_out;
925 err_best = f_err;
926 }
808 } 927 }
809 n++; 928 n++;
810 } while ((n <= MAX_N) && (f_out >= clock)); 929 } while ((n <= pll->max_n) && (f_out >= clock));
811 p += p_inc; 930 p += p_inc;
812 } while ((p <= p_max)); 931 } while ((p <= p_max));
813 932
@@ -818,21 +937,22 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
818 m = m_best; 937 m = m_best;
819 n = n_best; 938 n = n_best;
820 p = p_best; 939 p = p_best;
821 splitm(m, &m1, &m2); 940 splitm(index, m, &m1, &m2);
822 splitp(p, &p1, &p2); 941 splitp(index, p, &p1, &p2);
823 n1 = n - 2; 942 n1 = n - 2;
824 943
825 DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " 944 DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
826 "f: %d (%d), VCO: %d\n", 945 "f: %d (%d), VCO: %d\n",
827 m, m1, m2, n, n1, p, p1, p2, 946 m, m1, m2, n, n1, p, p1, p2,
828 CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2), 947 calc_vclock3(index, m, n, p),
829 CALC_VCLOCK3(m, n, p) * p); 948 calc_vclock(index, m1, m2, n1, p1, p2, 0),
949 calc_vclock3(index, m, n, p) * p);
830 *retm1 = m1; 950 *retm1 = m1;
831 *retm2 = m2; 951 *retm2 = m2;
832 *retn = n1; 952 *retn = n1;
833 *retp1 = p1; 953 *retp1 = p1;
834 *retp2 = p2; 954 *retp2 = p2;
835 *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2); 955 *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
836 956
837 return 0; 957 return 0;
838} 958}
@@ -860,6 +980,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
860 u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive; 980 u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
861 u32 vsync_pol, hsync_pol; 981 u32 vsync_pol, hsync_pol;
862 u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf; 982 u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
983 u32 stride_alignment;
863 984
864 DBG_MSG("intelfbhw_mode_to_hw\n"); 985 DBG_MSG("intelfbhw_mode_to_hw\n");
865 986
@@ -929,7 +1050,8 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
929 /* Desired clock in kHz */ 1050 /* Desired clock in kHz */
930 clock_target = 1000000000 / var->pixclock; 1051 clock_target = 1000000000 / var->pixclock;
931 1052
932 if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) { 1053 if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
1054 &n, &p1, &p2, &clock)) {
933 WRN_MSG("calc_pll_params failed\n"); 1055 WRN_MSG("calc_pll_params failed\n");
934 return 1; 1056 return 1;
935 } 1057 }
@@ -949,7 +1071,14 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
949 *dpll &= ~DPLL_P1_FORCE_DIV2; 1071 *dpll &= ~DPLL_P1_FORCE_DIV2;
950 *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | 1072 *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
951 (DPLL_P1_MASK << DPLL_P1_SHIFT)); 1073 (DPLL_P1_MASK << DPLL_P1_SHIFT));
952 *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); 1074
1075 if (IS_I9XX(dinfo)) {
1076 *dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
1077 *dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
1078 } else {
1079 *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
1080 }
1081
953 *fp0 = (n << FP_N_DIVISOR_SHIFT) | 1082 *fp0 = (n << FP_N_DIVISOR_SHIFT) |
954 (m1 << FP_M1_DIVISOR_SHIFT) | 1083 (m1 << FP_M1_DIVISOR_SHIFT) |
955 (m2 << FP_M2_DIVISOR_SHIFT); 1084 (m2 << FP_M2_DIVISOR_SHIFT);
@@ -1054,7 +1183,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
1054 *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) | 1183 *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
1055 (vactive << SRC_SIZE_VERT_SHIFT); 1184 (vactive << SRC_SIZE_VERT_SHIFT);
1056 1185
1057 hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8; 1186 hw->disp_a_stride = dinfo->pitch;
1058 DBG_MSG("pitch is %d\n", hw->disp_a_stride); 1187 DBG_MSG("pitch is %d\n", hw->disp_a_stride);
1059 1188
1060 hw->disp_a_base = hw->disp_a_stride * var->yoffset + 1189 hw->disp_a_base = hw->disp_a_stride * var->yoffset +
@@ -1063,9 +1192,11 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
1063 hw->disp_a_base += dinfo->fb.offset << 12; 1192 hw->disp_a_base += dinfo->fb.offset << 12;
1064 1193
1065 /* Check stride alignment. */ 1194 /* Check stride alignment. */
1066 if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) { 1195 stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
1196 STRIDE_ALIGNMENT;
1197 if (hw->disp_a_stride % stride_alignment != 0) {
1067 WRN_MSG("display stride %d has bad alignment %d\n", 1198 WRN_MSG("display stride %d has bad alignment %d\n",
1068 hw->disp_a_stride, STRIDE_ALIGNMENT); 1199 hw->disp_a_stride, stride_alignment);
1069 return 1; 1200 return 1;
1070 } 1201 }
1071 1202
@@ -1087,6 +1218,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
1087 u32 hsync_reg, htotal_reg, hblank_reg; 1218 u32 hsync_reg, htotal_reg, hblank_reg;
1088 u32 vsync_reg, vtotal_reg, vblank_reg; 1219 u32 vsync_reg, vtotal_reg, vblank_reg;
1089 u32 src_size_reg; 1220 u32 src_size_reg;
1221 u32 count, tmp_val[3];
1090 1222
1091 /* Assume single pipe, display plane A, analog CRT. */ 1223 /* Assume single pipe, display plane A, analog CRT. */
1092 1224
@@ -1155,6 +1287,27 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
1155 src_size_reg = SRC_SIZE_A; 1287 src_size_reg = SRC_SIZE_A;
1156 } 1288 }
1157 1289
1290 /* turn off pipe */
1291 tmp = INREG(pipe_conf_reg);
1292 tmp &= ~PIPECONF_ENABLE;
1293 OUTREG(pipe_conf_reg, tmp);
1294
1295 count = 0;
1296 do {
1297 tmp_val[count%3] = INREG(0x70000);
1298 if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2]))
1299 break;
1300 count++;
1301 udelay(1);
1302 if (count % 200 == 0) {
1303 tmp = INREG(pipe_conf_reg);
1304 tmp &= ~PIPECONF_ENABLE;
1305 OUTREG(pipe_conf_reg, tmp);
1306 }
1307 } while(count < 2000);
1308
1309 OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
1310
1158 /* Disable planes A and B. */ 1311 /* Disable planes A and B. */
1159 tmp = INREG(DSPACNTR); 1312 tmp = INREG(DSPACNTR);
1160 tmp &= ~DISPPLANE_PLANE_ENABLE; 1313 tmp &= ~DISPPLANE_PLANE_ENABLE;
@@ -1163,19 +1316,21 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
1163 tmp &= ~DISPPLANE_PLANE_ENABLE; 1316 tmp &= ~DISPPLANE_PLANE_ENABLE;
1164 OUTREG(DSPBCNTR, tmp); 1317 OUTREG(DSPBCNTR, tmp);
1165 1318
1166 /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ 1319 /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
1167 mdelay(20); 1320 mdelay(20);
1168 1321
1322 OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
1323 OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
1324 OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
1325
1169 /* Disable Sync */ 1326 /* Disable Sync */
1170 tmp = INREG(ADPA); 1327 tmp = INREG(ADPA);
1171 tmp &= ~ADPA_DPMS_CONTROL_MASK; 1328 tmp &= ~ADPA_DPMS_CONTROL_MASK;
1172 tmp |= ADPA_DPMS_D3; 1329 tmp |= ADPA_DPMS_D3;
1173 OUTREG(ADPA, tmp); 1330 OUTREG(ADPA, tmp);
1174 1331
1175 /* turn off pipe */ 1332 /* do some funky magic - xyzzy */
1176 tmp = INREG(pipe_conf_reg); 1333 OUTREG(0x61204, 0xabcd0000);
1177 tmp &= ~PIPECONF_ENABLE;
1178 OUTREG(pipe_conf_reg, tmp);
1179 1334
1180 /* turn off PLL */ 1335 /* turn off PLL */
1181 tmp = INREG(dpll_reg); 1336 tmp = INREG(dpll_reg);
@@ -1183,30 +1338,31 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
1183 OUTREG(dpll_reg, tmp); 1338 OUTREG(dpll_reg, tmp);
1184 1339
1185 /* Set PLL parameters */ 1340 /* Set PLL parameters */
1186 OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
1187 OUTREG(fp0_reg, *fp0); 1341 OUTREG(fp0_reg, *fp0);
1188 OUTREG(fp1_reg, *fp1); 1342 OUTREG(fp1_reg, *fp1);
1189 1343
1190 /* Set pipe parameters */ 1344 /* Enable PLL */
1191 OUTREG(hsync_reg, *hs); 1345 OUTREG(dpll_reg, *dpll);
1192 OUTREG(hblank_reg, *hb);
1193 OUTREG(htotal_reg, *ht);
1194 OUTREG(vsync_reg, *vs);
1195 OUTREG(vblank_reg, *vb);
1196 OUTREG(vtotal_reg, *vt);
1197 OUTREG(src_size_reg, *ss);
1198 1346
1199 /* Set DVOs B/C */ 1347 /* Set DVOs B/C */
1200 OUTREG(DVOB, hw->dvob); 1348 OUTREG(DVOB, hw->dvob);
1201 OUTREG(DVOC, hw->dvoc); 1349 OUTREG(DVOC, hw->dvoc);
1202 1350
1351 /* undo funky magic */
1352 OUTREG(0x61204, 0x00000000);
1353
1203 /* Set ADPA */ 1354 /* Set ADPA */
1355 OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
1204 OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3); 1356 OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
1205 1357
1206 /* Enable PLL */ 1358 /* Set pipe parameters */
1207 tmp = INREG(dpll_reg); 1359 OUTREG(hsync_reg, *hs);
1208 tmp |= DPLL_VCO_ENABLE; 1360 OUTREG(hblank_reg, *hb);
1209 OUTREG(dpll_reg, tmp); 1361 OUTREG(htotal_reg, *ht);
1362 OUTREG(vsync_reg, *vs);
1363 OUTREG(vblank_reg, *vb);
1364 OUTREG(vtotal_reg, *vt);
1365 OUTREG(src_size_reg, *ss);
1210 1366
1211 /* Enable pipe */ 1367 /* Enable pipe */
1212 OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE); 1368 OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
@@ -1231,7 +1387,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
1231 OUTREG(DSPACNTR, 1387 OUTREG(DSPACNTR,
1232 hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); 1388 hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
1233 mdelay(1); 1389 mdelay(1);
1234 } 1390 }
1235 } 1391 }
1236 1392
1237 OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); 1393 OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
@@ -1267,19 +1423,17 @@ wait_ring(struct intelfb_info *dinfo, int n)
1267 1423
1268 end = jiffies + (HZ * 3); 1424 end = jiffies + (HZ * 3);
1269 while (dinfo->ring_space < n) { 1425 while (dinfo->ring_space < n) {
1270 dinfo->ring_head = (u8 __iomem *)(INREG(PRI_RING_HEAD) & 1426 dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1271 RING_HEAD_MASK); 1427 if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head)
1272 if (dinfo->ring_tail + RING_MIN_FREE < 1428 dinfo->ring_space = dinfo->ring_head
1273 (u32 __iomem) dinfo->ring_head)
1274 dinfo->ring_space = (u32 __iomem) dinfo->ring_head
1275 - (dinfo->ring_tail + RING_MIN_FREE); 1429 - (dinfo->ring_tail + RING_MIN_FREE);
1276 else 1430 else
1277 dinfo->ring_space = (dinfo->ring.size + 1431 dinfo->ring_space = (dinfo->ring.size +
1278 (u32 __iomem) dinfo->ring_head) 1432 dinfo->ring_head)
1279 - (dinfo->ring_tail + RING_MIN_FREE); 1433 - (dinfo->ring_tail + RING_MIN_FREE);
1280 if ((u32 __iomem) dinfo->ring_head != last_head) { 1434 if (dinfo->ring_head != last_head) {
1281 end = jiffies + (HZ * 3); 1435 end = jiffies + (HZ * 3);
1282 last_head = (u32 __iomem) dinfo->ring_head; 1436 last_head = dinfo->ring_head;
1283 } 1437 }
1284 i++; 1438 i++;
1285 if (time_before(end, jiffies)) { 1439 if (time_before(end, jiffies)) {
@@ -1339,15 +1493,13 @@ refresh_ring(struct intelfb_info *dinfo)
1339 DBG_MSG("refresh_ring\n"); 1493 DBG_MSG("refresh_ring\n");
1340#endif 1494#endif
1341 1495
1342 dinfo->ring_head = (u8 __iomem *) (INREG(PRI_RING_HEAD) & 1496 dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1343 RING_HEAD_MASK);
1344 dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK; 1497 dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
1345 if (dinfo->ring_tail + RING_MIN_FREE < (u32 __iomem)dinfo->ring_head) 1498 if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head)
1346 dinfo->ring_space = (u32 __iomem) dinfo->ring_head 1499 dinfo->ring_space = dinfo->ring_head
1347 - (dinfo->ring_tail + RING_MIN_FREE); 1500 - (dinfo->ring_tail + RING_MIN_FREE);
1348 else 1501 else
1349 dinfo->ring_space = (dinfo->ring.size + 1502 dinfo->ring_space = (dinfo->ring.size + dinfo->ring_head)
1350 (u32 __iomem) dinfo->ring_head)
1351 - (dinfo->ring_tail + RING_MIN_FREE); 1503 - (dinfo->ring_tail + RING_MIN_FREE);
1352} 1504}
1353 1505
@@ -1616,7 +1768,7 @@ intelfbhw_cursor_init(struct intelfb_info *dinfo)
1616 DBG_MSG("intelfbhw_cursor_init\n"); 1768 DBG_MSG("intelfbhw_cursor_init\n");
1617#endif 1769#endif
1618 1770
1619 if (dinfo->mobile) { 1771 if (dinfo->mobile || IS_I9XX(dinfo)) {
1620 if (!dinfo->cursor.physical) 1772 if (!dinfo->cursor.physical)
1621 return; 1773 return;
1622 tmp = INREG(CURSOR_A_CONTROL); 1774 tmp = INREG(CURSOR_A_CONTROL);
@@ -1649,7 +1801,7 @@ intelfbhw_cursor_hide(struct intelfb_info *dinfo)
1649#endif 1801#endif
1650 1802
1651 dinfo->cursor_on = 0; 1803 dinfo->cursor_on = 0;
1652 if (dinfo->mobile) { 1804 if (dinfo->mobile || IS_I9XX(dinfo)) {
1653 if (!dinfo->cursor.physical) 1805 if (!dinfo->cursor.physical)
1654 return; 1806 return;
1655 tmp = INREG(CURSOR_A_CONTROL); 1807 tmp = INREG(CURSOR_A_CONTROL);
@@ -1679,7 +1831,7 @@ intelfbhw_cursor_show(struct intelfb_info *dinfo)
1679 if (dinfo->cursor_blanked) 1831 if (dinfo->cursor_blanked)
1680 return; 1832 return;
1681 1833
1682 if (dinfo->mobile) { 1834 if (dinfo->mobile || IS_I9XX(dinfo)) {
1683 if (!dinfo->cursor.physical) 1835 if (!dinfo->cursor.physical)
1684 return; 1836 return;
1685 tmp = INREG(CURSOR_A_CONTROL); 1837 tmp = INREG(CURSOR_A_CONTROL);
@@ -1705,14 +1857,18 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
1705#endif 1857#endif
1706 1858
1707 /* 1859 /*
1708 * Sets the position. The coordinates are assumed to already 1860 * Sets the position. The coordinates are assumed to already
1709 * have any offset adjusted. Assume that the cursor is never 1861 * have any offset adjusted. Assume that the cursor is never
1710 * completely off-screen, and that x, y are always >= 0. 1862 * completely off-screen, and that x, y are always >= 0.
1711 */ 1863 */
1712 1864
1713 tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | 1865 tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
1714 ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); 1866 ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
1715 OUTREG(CURSOR_A_POSITION, tmp); 1867 OUTREG(CURSOR_A_POSITION, tmp);
1868
1869 if (IS_I9XX(dinfo)) {
1870 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1871 }
1716} 1872}
1717 1873
1718void 1874void
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index ba1920159f52..10acda098b71 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -133,6 +133,7 @@
133#define DPLL_VGA_MODE_DISABLE (1 << 28) 133#define DPLL_VGA_MODE_DISABLE (1 << 28)
134#define DPLL_P2_MASK 1 134#define DPLL_P2_MASK 1
135#define DPLL_P2_SHIFT 23 135#define DPLL_P2_SHIFT 23
136#define DPLL_I9XX_P2_SHIFT 24
136#define DPLL_P1_FORCE_DIV2 (1 << 21) 137#define DPLL_P1_FORCE_DIV2 (1 << 21)
137#define DPLL_P1_MASK 0x1f 138#define DPLL_P1_MASK 0x1f
138#define DPLL_P1_SHIFT 16 139#define DPLL_P1_SHIFT 16
@@ -155,29 +156,8 @@
155/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ 156/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
156/* Clock values are in units of kHz */ 157/* Clock values are in units of kHz */
157#define PLL_REFCLK 48000 158#define PLL_REFCLK 48000
158#define MIN_VCO_FREQ 930000
159#define MAX_VCO_FREQ 1400000
160#define MIN_CLOCK 25000 159#define MIN_CLOCK 25000
161#define MAX_CLOCK 350000 160#define MAX_CLOCK 350000
162#define P_TRANSITION_CLOCK 165000
163#define MIN_M 108
164#define MAX_M 140
165#define MIN_M1 18
166#define MAX_M1 26
167#define MIN_M2 6
168#define MAX_M2 16
169#define MIN_P 4
170#define MAX_P 128
171#define MIN_P1 0
172#define MAX_P1 31
173#define MIN_N 3
174#define MAX_N 16
175
176#define CALC_VCLOCK(m1, m2, n, p1, p2) \
177 ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \
178 (((p1) + 2) * (1 << (p2 + 1))))
179
180#define CALC_VCLOCK3(m, n, p) ((PLL_REFCLK * (m) / (n)) / (p))
181 161
182/* Two pipes */ 162/* Two pipes */
183#define PIPE_A 0 163#define PIPE_A 0
@@ -522,8 +502,7 @@
522 502
523 503
524/* function protoypes */ 504/* function protoypes */
525extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, 505extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo);
526 int *chipset, int *mobile);
527extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, 506extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
528 int *stolen_size); 507 int *stolen_size);
529extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo); 508extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 23c1827b2d0b..f4ddd3431f17 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -102,6 +102,8 @@
102#include <linux/config.h> 102#include <linux/config.h>
103#include <linux/version.h> 103#include <linux/version.h>
104 104
105#define __OLD_VIDIOC_
106
105#include "matroxfb_base.h" 107#include "matroxfb_base.h"
106#include "matroxfb_misc.h" 108#include "matroxfb_misc.h"
107#include "matroxfb_accel.h" 109#include "matroxfb_accel.h"
@@ -158,9 +160,9 @@ static void update_crtc2(WPMINFO unsigned int pos) {
158 160
159 /* Make sure that displays are compatible */ 161 /* Make sure that displays are compatible */
160 if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel) 162 if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel)
161 && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual) 163 && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
162 && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length) 164 && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
163 ) { 165 ) {
164 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { 166 switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
165 case 16: 167 case 16:
166 case 32: 168 case 32:
@@ -224,7 +226,7 @@ static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp)
224 226
225int matroxfb_enable_irq(WPMINFO int reenable) { 227int matroxfb_enable_irq(WPMINFO int reenable) {
226 u_int32_t bm; 228 u_int32_t bm;
227 229
228 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) 230 if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
229 bm = 0x220; 231 bm = 0x220;
230 else 232 else
@@ -241,7 +243,7 @@ int matroxfb_enable_irq(WPMINFO int reenable) {
241 mga_outl(M_IEN, mga_inl(M_IEN) | bm); 243 mga_outl(M_IEN, mga_inl(M_IEN) | bm);
242 } else if (reenable) { 244 } else if (reenable) {
243 u_int32_t ien; 245 u_int32_t ien;
244 246
245 ien = mga_inl(M_IEN); 247 ien = mga_inl(M_IEN);
246 if ((ien & bm) != bm) { 248 if ((ien & bm) != bm) {
247 printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien); 249 printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
@@ -347,7 +349,7 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
347 mga_setr(M_EXTVGA_INDEX, 0x00, p2); 349 mga_setr(M_EXTVGA_INDEX, 0x00, p2);
348 } 350 }
349 matroxfb_DAC_unlock_irqrestore(flags); 351 matroxfb_DAC_unlock_irqrestore(flags);
350 352
351 update_crtc2(PMINFO pos); 353 update_crtc2(PMINFO pos);
352 354
353 CRITEND 355 CRITEND
@@ -390,7 +392,7 @@ static void matroxfb_remove(WPMINFO int dummy) {
390static int matroxfb_open(struct fb_info *info, int user) 392static int matroxfb_open(struct fb_info *info, int user)
391{ 393{
392 MINFO_FROM_INFO(info); 394 MINFO_FROM_INFO(info);
393 395
394 DBG_LOOP(__FUNCTION__) 396 DBG_LOOP(__FUNCTION__)
395 397
396 if (ACCESS_FBINFO(dead)) { 398 if (ACCESS_FBINFO(dead)) {
@@ -406,7 +408,7 @@ static int matroxfb_open(struct fb_info *info, int user)
406static int matroxfb_release(struct fb_info *info, int user) 408static int matroxfb_release(struct fb_info *info, int user)
407{ 409{
408 MINFO_FROM_INFO(info); 410 MINFO_FROM_INFO(info);
409 411
410 DBG_LOOP(__FUNCTION__) 412 DBG_LOOP(__FUNCTION__)
411 413
412 if (user) { 414 if (user) {
@@ -854,7 +856,7 @@ static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank)
854 vblank->flags |= FB_VBLANK_VBLANKING; 856 vblank->flags |= FB_VBLANK_VBLANKING;
855 if (test_bit(0, &ACCESS_FBINFO(irq_flags))) { 857 if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
856 vblank->flags |= FB_VBLANK_HAVE_COUNT; 858 vblank->flags |= FB_VBLANK_HAVE_COUNT;
857 /* Only one writer, aligned int value... 859 /* Only one writer, aligned int value...
858 it should work without lock and without atomic_t */ 860 it should work without lock and without atomic_t */
859 vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt; 861 vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt;
860 } 862 }
@@ -870,7 +872,7 @@ static int matroxfb_ioctl(struct fb_info *info,
870{ 872{
871 void __user *argp = (void __user *)arg; 873 void __user *argp = (void __user *)arg;
872 MINFO_FROM_INFO(info); 874 MINFO_FROM_INFO(info);
873 875
874 DBG(__FUNCTION__) 876 DBG(__FUNCTION__)
875 877
876 if (ACCESS_FBINFO(dead)) { 878 if (ACCESS_FBINFO(dead)) {
@@ -1081,7 +1083,7 @@ static int matroxfb_ioctl(struct fb_info *info,
1081 case VIDIOC_QUERYCAP: 1083 case VIDIOC_QUERYCAP:
1082 { 1084 {
1083 struct v4l2_capability r; 1085 struct v4l2_capability r;
1084 1086
1085 memset(&r, 0, sizeof(r)); 1087 memset(&r, 0, sizeof(r));
1086 strcpy(r.driver, "matroxfb"); 1088 strcpy(r.driver, "matroxfb");
1087 strcpy(r.card, "Matrox"); 1089 strcpy(r.card, "Matrox");
@@ -1091,7 +1093,7 @@ static int matroxfb_ioctl(struct fb_info *info,
1091 if (copy_to_user(argp, &r, sizeof(r))) 1093 if (copy_to_user(argp, &r, sizeof(r)))
1092 return -EFAULT; 1094 return -EFAULT;
1093 return 0; 1095 return 0;
1094 1096
1095 } 1097 }
1096 case VIDIOC_QUERYCTRL: 1098 case VIDIOC_QUERYCTRL:
1097 { 1099 {
@@ -1690,8 +1692,8 @@ static int initMatrox2(WPMINFO struct board* b){
1690 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd); 1692 pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd);
1691 mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */ 1693 mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
1692 mga_option |= MX_OPTION_BSWAP; 1694 mga_option |= MX_OPTION_BSWAP;
1693 /* disable palette snooping */ 1695 /* disable palette snooping */
1694 cmd &= ~PCI_COMMAND_VGA_PALETTE; 1696 cmd &= ~PCI_COMMAND_VGA_PALETTE;
1695 if (pci_dev_present(intel_82437)) { 1697 if (pci_dev_present(intel_82437)) {
1696 if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) { 1698 if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) {
1697 printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n"); 1699 printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
@@ -1809,12 +1811,12 @@ static int initMatrox2(WPMINFO struct board* b){
1809 1811
1810 if (fv) { 1812 if (fv) {
1811 tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres 1813 tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
1812 + vesafb_defined.lower_margin + vesafb_defined.vsync_len); 1814 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
1813 if ((tmp < fh) || (fh == 0)) fh = tmp; 1815 if ((tmp < fh) || (fh == 0)) fh = tmp;
1814 } 1816 }
1815 if (fh) { 1817 if (fh) {
1816 tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres 1818 tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
1817 + vesafb_defined.right_margin + vesafb_defined.hsync_len); 1819 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
1818 if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp; 1820 if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
1819 } 1821 }
1820 tmp = (maxclk + 499) / 500; 1822 tmp = (maxclk + 499) / 500;
@@ -1890,14 +1892,14 @@ static int initMatrox2(WPMINFO struct board* b){
1890 1892
1891 /* there is no console on this fb... but we have to initialize hardware 1893 /* there is no console on this fb... but we have to initialize hardware
1892 * until someone tells me what is proper thing to do */ 1894 * until someone tells me what is proper thing to do */
1893 if (!ACCESS_FBINFO(initialized)) { 1895 if (!ACCESS_FBINFO(initialized)) {
1894 printk(KERN_INFO "fb%d: initializing hardware\n", 1896 printk(KERN_INFO "fb%d: initializing hardware\n",
1895 ACCESS_FBINFO(fbcon.node)); 1897 ACCESS_FBINFO(fbcon.node));
1896 /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var 1898 /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
1897 * already before, so register_framebuffer works correctly. */ 1899 * already before, so register_framebuffer works correctly. */
1898 vesafb_defined.activate |= FB_ACTIVATE_FORCE; 1900 vesafb_defined.activate |= FB_ACTIVATE_FORCE;
1899 fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined); 1901 fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
1900 } 1902 }
1901 1903
1902 return 0; 1904 return 0;
1903failVideoIO:; 1905failVideoIO:;
@@ -2356,7 +2358,7 @@ static int __init matroxfb_setup(char *options) {
2356 else if (!strncmp(this_opt, "dfp:", 4)) { 2358 else if (!strncmp(this_opt, "dfp:", 4)) {
2357 dfp_type = simple_strtoul(this_opt+4, NULL, 0); 2359 dfp_type = simple_strtoul(this_opt+4, NULL, 0);
2358 dfp = 1; 2360 dfp = 1;
2359 } 2361 }
2360#ifdef CONFIG_PPC_PMAC 2362#ifdef CONFIG_PPC_PMAC
2361 else if (!strncmp(this_opt, "vmode:", 6)) { 2363 else if (!strncmp(this_opt, "vmode:", 6)) {
2362 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); 2364 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 743e7ad26acc..f85421bf7cb5 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -55,7 +55,7 @@ static struct fb_var_screeninfo maxinefb_defined = {
55}; 55};
56 56
57static struct fb_fix_screeninfo maxinefb_fix = { 57static struct fb_fix_screeninfo maxinefb_fix = {
58 .id = "Maxine onboard graphics 1024x768x8", 58 .id = "Maxine",
59 .smem_len = (1024*768), 59 .smem_len = (1024*768),
60 .type = FB_TYPE_PACKED_PIXELS, 60 .type = FB_TYPE_PACKED_PIXELS,
61 .visual = FB_VISUAL_PSEUDOCOLOR, 61 .visual = FB_VISUAL_PSEUDOCOLOR,
@@ -107,8 +107,6 @@ static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
107 107
108static struct fb_ops maxinefb_ops = { 108static struct fb_ops maxinefb_ops = {
109 .owner = THIS_MODULE, 109 .owner = THIS_MODULE,
110 .fb_get_fix = gen_get_fix,
111 .fb_get_var = gen_get_var,
112 .fb_setcolreg = maxinefb_setcolreg, 110 .fb_setcolreg = maxinefb_setcolreg,
113 .fb_fillrect = cfb_fillrect, 111 .fb_fillrect = cfb_fillrect,
114 .fb_copyarea = cfb_copyarea, 112 .fb_copyarea = cfb_copyarea,
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
index 690d37e8de5b..ca47432113e0 100644
--- a/drivers/video/nvidia/Makefile
+++ b/drivers/video/nvidia/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_FB_NVIDIA) += nvidiafb.o
7nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ 7nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \
8 nv_accel.o 8 nv_accel.o
9nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o 9nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
10nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT) += nv_backlight.o
10nvidiafb-$(CONFIG_PPC_OF) += nv_of.o 11nvidiafb-$(CONFIG_PPC_OF) += nv_of.o
11 12
12nvidiafb-objs := $(nvidiafb-y) \ No newline at end of file 13nvidiafb-objs := $(nvidiafb-y)
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
new file mode 100644
index 000000000000..1c1c10c699c5
--- /dev/null
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -0,0 +1,175 @@
1/*
2 * Backlight code for nVidia based graphic cards
3 *
4 * Copyright 2004 Antonino Daplas <adaplas@pol.net>
5 * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/backlight.h>
13#include <linux/fb.h>
14#include <linux/pci.h>
15#include "nv_local.h"
16#include "nv_type.h"
17#include "nv_proto.h"
18
19#ifdef CONFIG_PMAC_BACKLIGHT
20#include <asm/backlight.h>
21#include <asm/machdep.h>
22#endif
23
24/* We do not have any information about which values are allowed, thus
25 * we used safe values.
26 */
27#define MIN_LEVEL 0x158
28#define MAX_LEVEL 0x534
29
30static struct backlight_properties nvidia_bl_data;
31
32static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
33 int level)
34{
35 struct fb_info *info = pci_get_drvdata(par->pci_dev);
36 int nlevel;
37
38 /* Get and convert the value */
39 mutex_lock(&info->bl_mutex);
40 nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
41 mutex_unlock(&info->bl_mutex);
42
43 if (nlevel < 0)
44 nlevel = 0;
45 else if (nlevel < MIN_LEVEL)
46 nlevel = MIN_LEVEL;
47 else if (nlevel > MAX_LEVEL)
48 nlevel = MAX_LEVEL;
49
50 return nlevel;
51}
52
53static int nvidia_bl_update_status(struct backlight_device *bd)
54{
55 struct nvidia_par *par = class_get_devdata(&bd->class_dev);
56 u32 tmp_pcrt, tmp_pmc, fpcontrol;
57 int level;
58
59 if (!par->FlatPanel)
60 return 0;
61
62 if (bd->props->power != FB_BLANK_UNBLANK ||
63 bd->props->fb_blank != FB_BLANK_UNBLANK)
64 level = 0;
65 else
66 level = bd->props->brightness;
67
68 tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
69 tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
70 fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
71
72 if (level > 0) {
73 tmp_pcrt |= 0x1;
74 tmp_pmc |= (1 << 31); /* backlight bit */
75 tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
76 fpcontrol |= par->fpSyncs;
77 } else
78 fpcontrol |= 0x20000022;
79
80 NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
81 NV_WR32(par->PMC, 0x10F0, tmp_pmc);
82 NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
83
84 return 0;
85}
86
87static int nvidia_bl_get_brightness(struct backlight_device *bd)
88{
89 return bd->props->brightness;
90}
91
92static struct backlight_properties nvidia_bl_data = {
93 .owner = THIS_MODULE,
94 .get_brightness = nvidia_bl_get_brightness,
95 .update_status = nvidia_bl_update_status,
96 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
97};
98
99void nvidia_bl_init(struct nvidia_par *par)
100{
101 struct fb_info *info = pci_get_drvdata(par->pci_dev);
102 struct backlight_device *bd;
103 char name[12];
104
105 if (!par->FlatPanel)
106 return;
107
108#ifdef CONFIG_PMAC_BACKLIGHT
109 if (!machine_is(powermac) ||
110 !pmac_has_backlight_type("mnca"))
111 return;
112#endif
113
114 snprintf(name, sizeof(name), "nvidiabl%d", info->node);
115
116 bd = backlight_device_register(name, par, &nvidia_bl_data);
117 if (IS_ERR(bd)) {
118 info->bl_dev = NULL;
119 printk("nvidia: Backlight registration failed\n");
120 goto error;
121 }
122
123 mutex_lock(&info->bl_mutex);
124 info->bl_dev = bd;
125 fb_bl_default_curve(info, 0,
126 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
127 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
128 mutex_unlock(&info->bl_mutex);
129
130 up(&bd->sem);
131 bd->props->brightness = nvidia_bl_data.max_brightness;
132 bd->props->power = FB_BLANK_UNBLANK;
133 bd->props->update_status(bd);
134 down(&bd->sem);
135
136#ifdef CONFIG_PMAC_BACKLIGHT
137 mutex_lock(&pmac_backlight_mutex);
138 if (!pmac_backlight)
139 pmac_backlight = bd;
140 mutex_unlock(&pmac_backlight_mutex);
141#endif
142
143 printk("nvidia: Backlight initialized (%s)\n", name);
144
145 return;
146
147error:
148 return;
149}
150
151void nvidia_bl_exit(struct nvidia_par *par)
152{
153 struct fb_info *info = pci_get_drvdata(par->pci_dev);
154
155#ifdef CONFIG_PMAC_BACKLIGHT
156 mutex_lock(&pmac_backlight_mutex);
157#endif
158
159 mutex_lock(&info->bl_mutex);
160 if (info->bl_dev) {
161#ifdef CONFIG_PMAC_BACKLIGHT
162 if (pmac_backlight == info->bl_dev)
163 pmac_backlight = NULL;
164#endif
165
166 backlight_device_unregister(info->bl_dev);
167
168 printk("nvidia: Backlight unloaded\n");
169 }
170 mutex_unlock(&info->bl_mutex);
171
172#ifdef CONFIG_PMAC_BACKLIGHT
173 mutex_unlock(&pmac_backlight_mutex);
174#endif
175}
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index b149a690ee0f..6fba656cd56b 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -63,4 +63,14 @@ extern void nvidiafb_imageblit(struct fb_info *info,
63 const struct fb_image *image); 63 const struct fb_image *image);
64extern int nvidiafb_sync(struct fb_info *info); 64extern int nvidiafb_sync(struct fb_info *info);
65extern u8 byte_rev[256]; 65extern u8 byte_rev[256];
66
67/* in nv_backlight.h */
68#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
69extern void nvidia_bl_init(struct nvidia_par *par);
70extern void nvidia_bl_exit(struct nvidia_par *par);
71#else
72static inline void nvidia_bl_init(struct nvidia_par *par) {}
73static inline void nvidia_bl_exit(struct nvidia_par *par) {}
74#endif
75
66#endif /* __NV_PROTO_H__ */ 76#endif /* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 093ab9977c7c..03a7c1e9ce38 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -22,6 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/console.h> 24#include <linux/console.h>
25#include <linux/backlight.h>
25#ifdef CONFIG_MTRR 26#ifdef CONFIG_MTRR
26#include <asm/mtrr.h> 27#include <asm/mtrr.h>
27#endif 28#endif
@@ -29,10 +30,6 @@
29#include <asm/prom.h> 30#include <asm/prom.h>
30#include <asm/pci-bridge.h> 31#include <asm/pci-bridge.h>
31#endif 32#endif
32#ifdef CONFIG_PMAC_BACKLIGHT
33#include <asm/machdep.h>
34#include <asm/backlight.h>
35#endif
36 33
37#include "nv_local.h" 34#include "nv_local.h"
38#include "nv_type.h" 35#include "nv_type.h"
@@ -470,75 +467,6 @@ static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
470 .vmode = FB_VMODE_NONINTERLACED 467 .vmode = FB_VMODE_NONINTERLACED
471}; 468};
472 469
473/*
474 * Backlight control
475 */
476#ifdef CONFIG_PMAC_BACKLIGHT
477
478static int nvidia_backlight_levels[] = {
479 0x158,
480 0x192,
481 0x1c6,
482 0x200,
483 0x234,
484 0x268,
485 0x2a2,
486 0x2d6,
487 0x310,
488 0x344,
489 0x378,
490 0x3b2,
491 0x3e6,
492 0x41a,
493 0x454,
494 0x534,
495};
496
497/* ------------------------------------------------------------------------- *
498 *
499 * Backlight operations
500 *
501 * ------------------------------------------------------------------------- */
502
503static int nvidia_set_backlight_enable(int on, int level, void *data)
504{
505 struct nvidia_par *par = data;
506 u32 tmp_pcrt, tmp_pmc, fpcontrol;
507
508 tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
509 tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
510 fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
511
512 if (on && (level > BACKLIGHT_OFF)) {
513 tmp_pcrt |= 0x1;
514 tmp_pmc |= (1 << 31); // backlight bit
515 tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
516 }
517
518 if (on)
519 fpcontrol |= par->fpSyncs;
520 else
521 fpcontrol |= 0x20000022;
522
523 NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
524 NV_WR32(par->PMC, 0x10F0, tmp_pmc);
525 NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
526
527 return 0;
528}
529
530static int nvidia_set_backlight_level(int level, void *data)
531{
532 return nvidia_set_backlight_enable(1, level, data);
533}
534
535static struct backlight_controller nvidia_backlight_controller = {
536 nvidia_set_backlight_enable,
537 nvidia_set_backlight_level
538};
539
540#endif /* CONFIG_PMAC_BACKLIGHT */
541
542static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8, 470static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
543 u16 bg, u16 fg, u32 w, u32 h) 471 u16 bg, u16 fg, u32 w, u32 h)
544{ 472{
@@ -1355,10 +1283,15 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
1355 NVWriteSeq(par, 0x01, tmp); 1283 NVWriteSeq(par, 0x01, tmp);
1356 NVWriteCrtc(par, 0x1a, vesa); 1284 NVWriteCrtc(par, 0x1a, vesa);
1357 1285
1358#ifdef CONFIG_PMAC_BACKLIGHT 1286#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
1359 if (par->FlatPanel && machine_is(powermac)) { 1287 mutex_lock(&info->bl_mutex);
1360 set_backlight_enable(!blank); 1288 if (info->bl_dev) {
1289 down(&info->bl_dev->sem);
1290 info->bl_dev->props->power = blank;
1291 info->bl_dev->props->update_status(info->bl_dev);
1292 up(&info->bl_dev->sem);
1361 } 1293 }
1294 mutex_unlock(&info->bl_mutex);
1362#endif 1295#endif
1363 1296
1364 NVTRACE_LEAVE(); 1297 NVTRACE_LEAVE();
@@ -1741,11 +1674,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
1741 "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", 1674 "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
1742 info->fix.id, 1675 info->fix.id,
1743 par->FbMapSize / (1024 * 1024), info->fix.smem_start); 1676 par->FbMapSize / (1024 * 1024), info->fix.smem_start);
1744#ifdef CONFIG_PMAC_BACKLIGHT 1677
1745 if (par->FlatPanel && machine_is(powermac)) 1678 nvidia_bl_init(par);
1746 register_backlight_controller(&nvidia_backlight_controller, 1679
1747 par, "mnca");
1748#endif
1749 NVTRACE_LEAVE(); 1680 NVTRACE_LEAVE();
1750 return 0; 1681 return 0;
1751 1682
@@ -1775,6 +1706,8 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
1775 1706
1776 NVTRACE_ENTER(); 1707 NVTRACE_ENTER();
1777 1708
1709 nvidia_bl_exit(par);
1710
1778 unregister_framebuffer(info); 1711 unregister_framebuffer(info);
1779#ifdef CONFIG_MTRR 1712#ifdef CONFIG_MTRR
1780 if (par->mtrr.vram_valid) 1713 if (par->mtrr.vram_valid)
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9308f0f165..d4384ab1df65 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -41,6 +41,7 @@
41#include <linux/fb.h> 41#include <linux/fb.h>
42#include <linux/init.h> 42#include <linux/init.h>
43#include <linux/pci.h> 43#include <linux/pci.h>
44#include <linux/backlight.h>
44#ifdef CONFIG_MTRR 45#ifdef CONFIG_MTRR
45#include <asm/mtrr.h> 46#include <asm/mtrr.h>
46#endif 47#endif
@@ -272,34 +273,154 @@ static const struct riva_regs reg_template = {
272/* 273/*
273 * Backlight control 274 * Backlight control
274 */ 275 */
275#ifdef CONFIG_PMAC_BACKLIGHT 276#ifdef CONFIG_FB_RIVA_BACKLIGHT
277/* We do not have any information about which values are allowed, thus
278 * we used safe values.
279 */
280#define MIN_LEVEL 0x158
281#define MAX_LEVEL 0x534
276 282
277static int riva_backlight_levels[] = { 283static struct backlight_properties riva_bl_data;
278 0x158, 284
279 0x192, 285static int riva_bl_get_level_brightness(struct riva_par *par,
280 0x1c6, 286 int level)
281 0x200, 287{
282 0x234, 288 struct fb_info *info = pci_get_drvdata(par->pdev);
283 0x268, 289 int nlevel;
284 0x2a2, 290
285 0x2d6, 291 /* Get and convert the value */
286 0x310, 292 mutex_lock(&info->bl_mutex);
287 0x344, 293 nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
288 0x378, 294 mutex_unlock(&info->bl_mutex);
289 0x3b2, 295
290 0x3e6, 296 if (nlevel < 0)
291 0x41a, 297 nlevel = 0;
292 0x454, 298 else if (nlevel < MIN_LEVEL)
293 0x534, 299 nlevel = MIN_LEVEL;
294}; 300 else if (nlevel > MAX_LEVEL)
301 nlevel = MAX_LEVEL;
302
303 return nlevel;
304}
305
306static int riva_bl_update_status(struct backlight_device *bd)
307{
308 struct riva_par *par = class_get_devdata(&bd->class_dev);
309 U032 tmp_pcrt, tmp_pmc;
310 int level;
311
312 if (bd->props->power != FB_BLANK_UNBLANK ||
313 bd->props->fb_blank != FB_BLANK_UNBLANK)
314 level = 0;
315 else
316 level = bd->props->brightness;
317
318 tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
319 tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
320 if(level > 0) {
321 tmp_pcrt |= 0x1;
322 tmp_pmc |= (1 << 31); /* backlight bit */
323 tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
324 }
325 par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
326 par->riva.PMC[0x10F0/4] = tmp_pmc;
327
328 return 0;
329}
330
331static int riva_bl_get_brightness(struct backlight_device *bd)
332{
333 return bd->props->brightness;
334}
295 335
296static int riva_set_backlight_enable(int on, int level, void *data); 336static struct backlight_properties riva_bl_data = {
297static int riva_set_backlight_level(int level, void *data); 337 .owner = THIS_MODULE,
298static struct backlight_controller riva_backlight_controller = { 338 .get_brightness = riva_bl_get_brightness,
299 riva_set_backlight_enable, 339 .update_status = riva_bl_update_status,
300 riva_set_backlight_level 340 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
301}; 341};
302#endif /* CONFIG_PMAC_BACKLIGHT */ 342
343static void riva_bl_init(struct riva_par *par)
344{
345 struct fb_info *info = pci_get_drvdata(par->pdev);
346 struct backlight_device *bd;
347 char name[12];
348
349 if (!par->FlatPanel)
350 return;
351
352#ifdef CONFIG_PMAC_BACKLIGHT
353 if (!machine_is(powermac) ||
354 !pmac_has_backlight_type("mnca"))
355 return;
356#endif
357
358 snprintf(name, sizeof(name), "rivabl%d", info->node);
359
360 bd = backlight_device_register(name, par, &riva_bl_data);
361 if (IS_ERR(bd)) {
362 info->bl_dev = NULL;
363 printk("riva: Backlight registration failed\n");
364 goto error;
365 }
366
367 mutex_lock(&info->bl_mutex);
368 info->bl_dev = bd;
369 fb_bl_default_curve(info, 0,
370 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
371 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
372 mutex_unlock(&info->bl_mutex);
373
374 up(&bd->sem);
375 bd->props->brightness = riva_bl_data.max_brightness;
376 bd->props->power = FB_BLANK_UNBLANK;
377 bd->props->update_status(bd);
378 down(&bd->sem);
379
380#ifdef CONFIG_PMAC_BACKLIGHT
381 mutex_lock(&pmac_backlight_mutex);
382 if (!pmac_backlight)
383 pmac_backlight = bd;
384 mutex_unlock(&pmac_backlight_mutex);
385#endif
386
387 printk("riva: Backlight initialized (%s)\n", name);
388
389 return;
390
391error:
392 return;
393}
394
395static void riva_bl_exit(struct riva_par *par)
396{
397 struct fb_info *info = pci_get_drvdata(par->pdev);
398
399#ifdef CONFIG_PMAC_BACKLIGHT
400 mutex_lock(&pmac_backlight_mutex);
401#endif
402
403 mutex_lock(&info->bl_mutex);
404 if (info->bl_dev) {
405#ifdef CONFIG_PMAC_BACKLIGHT
406 if (pmac_backlight == info->bl_dev)
407 pmac_backlight = NULL;
408#endif
409
410 backlight_device_unregister(info->bl_dev);
411
412 printk("riva: Backlight unloaded\n");
413 }
414 mutex_unlock(&info->bl_mutex);
415
416#ifdef CONFIG_PMAC_BACKLIGHT
417 mutex_unlock(&pmac_backlight_mutex);
418#endif
419}
420#else
421static inline void riva_bl_init(struct riva_par *par) {}
422static inline void riva_bl_exit(struct riva_par *par) {}
423#endif /* CONFIG_FB_RIVA_BACKLIGHT */
303 424
304/* ------------------------------------------------------------------------- * 425/* ------------------------------------------------------------------------- *
305 * 426 *
@@ -973,36 +1094,6 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
973 1094
974/* ------------------------------------------------------------------------- * 1095/* ------------------------------------------------------------------------- *
975 * 1096 *
976 * Backlight operations
977 *
978 * ------------------------------------------------------------------------- */
979
980#ifdef CONFIG_PMAC_BACKLIGHT
981static int riva_set_backlight_enable(int on, int level, void *data)
982{
983 struct riva_par *par = data;
984 U032 tmp_pcrt, tmp_pmc;
985
986 tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
987 tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
988 if(on && (level > BACKLIGHT_OFF)) {
989 tmp_pcrt |= 0x1;
990 tmp_pmc |= (1 << 31); // backlight bit
991 tmp_pmc |= riva_backlight_levels[level-1] << 16; // level
992 }
993 par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
994 par->riva.PMC[0x10F0/4] = tmp_pmc;
995 return 0;
996}
997
998static int riva_set_backlight_level(int level, void *data)
999{
1000 return riva_set_backlight_enable(1, level, data);
1001}
1002#endif /* CONFIG_PMAC_BACKLIGHT */
1003
1004/* ------------------------------------------------------------------------- *
1005 *
1006 * framebuffer operations 1097 * framebuffer operations
1007 * 1098 *
1008 * ------------------------------------------------------------------------- */ 1099 * ------------------------------------------------------------------------- */
@@ -1247,10 +1338,15 @@ static int rivafb_blank(int blank, struct fb_info *info)
1247 SEQout(par, 0x01, tmp); 1338 SEQout(par, 0x01, tmp);
1248 CRTCout(par, 0x1a, vesa); 1339 CRTCout(par, 0x1a, vesa);
1249 1340
1250#ifdef CONFIG_PMAC_BACKLIGHT 1341#ifdef CONFIG_FB_RIVA_BACKLIGHT
1251 if ( par->FlatPanel && machine_is(powermac)) { 1342 mutex_lock(&info->bl_mutex);
1252 set_backlight_enable(!blank); 1343 if (info->bl_dev) {
1344 down(&info->bl_dev->sem);
1345 info->bl_dev->props->power = blank;
1346 info->bl_dev->props->update_status(info->bl_dev);
1347 up(&info->bl_dev->sem);
1253 } 1348 }
1349 mutex_unlock(&info->bl_mutex);
1254#endif 1350#endif
1255 1351
1256 NVTRACE_LEAVE(); 1352 NVTRACE_LEAVE();
@@ -2037,11 +2133,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
2037 RIVAFB_VERSION, 2133 RIVAFB_VERSION,
2038 info->fix.smem_len / (1024 * 1024), 2134 info->fix.smem_len / (1024 * 1024),
2039 info->fix.smem_start); 2135 info->fix.smem_start);
2040#ifdef CONFIG_PMAC_BACKLIGHT 2136
2041 if (default_par->FlatPanel && machine_is(powermac)) 2137 riva_bl_init(info->par);
2042 register_backlight_controller(&riva_backlight_controller, 2138
2043 default_par, "mnca");
2044#endif
2045 NVTRACE_LEAVE(); 2139 NVTRACE_LEAVE();
2046 return 0; 2140 return 0;
2047 2141
@@ -2074,6 +2168,8 @@ static void __exit rivafb_remove(struct pci_dev *pd)
2074 2168
2075 NVTRACE_ENTER(); 2169 NVTRACE_ENTER();
2076 2170
2171 riva_bl_exit(par);
2172
2077#ifdef CONFIG_FB_RIVA_I2C 2173#ifdef CONFIG_FB_RIVA_I2C
2078 riva_delete_i2c_busses(par); 2174 riva_delete_i2c_busses(par);
2079 kfree(par->EDID); 2175 kfree(par->EDID);
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 9ac2d3171187..41f8c2d93892 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -551,7 +551,7 @@ static inline void enable_mmio(void)
551#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F) 551#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
552 552
553/* Return flat panel's maximum x resolution */ 553/* Return flat panel's maximum x resolution */
554static int __init get_nativex(void) 554static int __devinit get_nativex(void)
555{ 555{
556 int x,y,tmp; 556 int x,y,tmp;
557 557
@@ -658,7 +658,7 @@ static void set_number_of_lines(int lines)
658 * If we see that FP is active we assume we have one. 658 * If we see that FP is active we assume we have one.
659 * Otherwise we have a CRT display.User can override. 659 * Otherwise we have a CRT display.User can override.
660 */ 660 */
661static unsigned int __init get_displaytype(void) 661static unsigned int __devinit get_displaytype(void)
662{ 662{
663 if (fp) 663 if (fp)
664 return DISPLAY_FP; 664 return DISPLAY_FP;
@@ -668,7 +668,7 @@ static unsigned int __init get_displaytype(void)
668} 668}
669 669
670/* Try detecting the video memory size */ 670/* Try detecting the video memory size */
671static unsigned int __init get_memsize(void) 671static unsigned int __devinit get_memsize(void)
672{ 672{
673 unsigned char tmp, tmp2; 673 unsigned char tmp, tmp2;
674 unsigned int k; 674 unsigned int k;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index f3f16fd9f231..4fd2a272e03d 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1351,7 +1351,7 @@ static int __init vga16fb_probe(struct device *device)
1351 } 1351 }
1352 1352
1353 /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ 1353 /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
1354 info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); 1354 info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
1355 1355
1356 if (!info->screen_base) { 1356 if (!info->screen_base) {
1357 printk(KERN_ERR "vga16fb: unable to map device\n"); 1357 printk(KERN_ERR "vga16fb: unable to map device\n");