diff options
Diffstat (limited to 'drivers/video')
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 | ||
89 | config FB_BACKLIGHT | ||
90 | bool | ||
91 | depends on FB | ||
92 | default n | ||
93 | |||
89 | config FB_MODE_HELPERS | 94 | config 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 | ||
175 | choice | ||
176 | |||
177 | depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X) | ||
178 | prompt "LCD Panel" | ||
179 | default FB_ARMCLCD_SHARP_LQ035Q7DB02 | ||
180 | |||
181 | config 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 | |||
189 | config 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 | |||
196 | config 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 | |||
203 | config 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 | |||
211 | config 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 | |||
224 | config 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 | |||
230 | config FB_ARMCLCD_HITACHI | ||
231 | bool "Hitachi Wide Screen 800x480" | ||
232 | help | ||
233 | This is an implementation of the Hitachi 800x480. | ||
234 | |||
235 | endchoice | ||
236 | |||
237 | |||
170 | config FB_ACORN | 238 | config 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 | ||
725 | config 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 | |||
657 | config FB_RIVA | 735 | config 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 | ||
773 | config 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 | |||
695 | config FB_I810 | 783 | config 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 | ||
744 | config FB_INTEL | 832 | config 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 | |||
933 | config FB_RADEON_I2C | 1022 | config 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 | ||
1029 | config 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 | |||
940 | config FB_RADEON_DEBUG | 1039 | config 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 | ||
1063 | config 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 | |||
964 | config FB_ATY | 1073 | config 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 | ||
1115 | config 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 | |||
1006 | config FB_S3TRIO | 1125 | config 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 | ||
11 | radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o | 11 | radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o |
12 | radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o | 12 | radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o |
13 | radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT) += radeon_backlight.o | ||
13 | radeonfb-objs := $(radeonfb-y) | 14 | radeonfb-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 | ||
484 | static int aty128_set_backlight_enable(int on, int level, void* data); | ||
485 | static int aty128_set_backlight_level(int level, void* data); | ||
486 | |||
487 | static 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) | |||
1258 | static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) | 1249 | static 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 | |||
1705 | static struct backlight_properties aty128_bl_data; | ||
1706 | |||
1707 | static 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 | |||
1735 | static 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 | |||
1788 | static int aty128_bl_get_brightness(struct backlight_device *bd) | ||
1789 | { | ||
1790 | return bd->props->brightness; | ||
1791 | } | ||
1792 | |||
1793 | static 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 | |||
1800 | static 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 | |||
1848 | error: | ||
1849 | return; | ||
1850 | } | ||
1851 | |||
1852 | static 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 | ||
2142 | static 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 | |||
2155 | static 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 | |||
2202 | static 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 | /* | 2123 | static struct backlight_properties aty_bl_data; |
2121 | * LCD backlight control | ||
2122 | */ | ||
2123 | 2124 | ||
2124 | static int backlight_conv[] = { | 2125 | static 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 | ||
2129 | static 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 | |||
2143 | static 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 | ||
2147 | static int aty_set_backlight_level(int level, void *data) | 2168 | static 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 | ||
2152 | static struct backlight_controller aty_backlight_controller = { | 2173 | static 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 | |
2180 | static 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 | |||
2224 | error: | ||
2225 | return; | ||
2226 | } | ||
2227 | |||
2228 | static 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 | ||
2158 | static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) | 2256 | static 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 | ||
3732 | static void __exit atyfb_exit(void) | 3858 | static 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 | ||
3737 | module_init(atyfb_init); | 3865 | module_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 | |||
22 | static struct backlight_properties radeon_bl_data; | ||
23 | |||
24 | struct radeon_bl_privdata { | ||
25 | struct radeonfb_info *rinfo; | ||
26 | uint8_t negative; | ||
27 | }; | ||
28 | |||
29 | static 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 | |||
54 | static 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 | |||
131 | static int radeon_bl_get_brightness(struct backlight_device *bd) | ||
132 | { | ||
133 | return bd->props->brightness; | ||
134 | } | ||
135 | |||
136 | static 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 | |||
143 | void 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 | |||
215 | error: | ||
216 | kfree(pdata); | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | void 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 | ||
284 | static int radeon_set_backlight_enable(int on, int level, void *data); | ||
285 | static int radeon_set_backlight_level(int level, void *data); | ||
286 | static 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 | |||
294 | static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) | 276 | static 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 | */ | ||
1923 | static int backlight_conv_m6[] = { | ||
1924 | 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e, | ||
1925 | 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24 | ||
1926 | }; | ||
1927 | static 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 | */ | ||
1939 | static 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 | |||
2019 | static 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_ | |||
625 | extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | 625 | extern 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 | ||
630 | extern void radeonfb_bl_init(struct radeonfb_info *rinfo); | ||
631 | extern void radeonfb_bl_exit(struct radeonfb_info *rinfo); | ||
632 | #else | ||
633 | static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} | ||
634 | static 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 | */ |
215 | int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi) | 215 | int 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 | */ |
317 | int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) | 320 | int 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 | */ |
383 | int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | 388 | int 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 | ||
598 | int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level) | 605 | int 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 | ||
604 | int au1100fb_drv_resume(struct device *dev, u32 level) | 611 | int 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) | |||
148 | static int chipsfb_blank(int blank, struct fb_info *info) | 148 | static 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 | ||
423 | static 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 | |||
457 | static 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 | ||
437 | int fb_init_class_device(struct fb_info *fb_info) | 504 | int 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 | */ | ||
531 | void 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 | } | ||
544 | EXPORT_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 | ||
131 | struct intelfb_hwstate { | 136 | struct 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 | ||
284 | extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); | 294 | extern 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 | ||
135 | static void __devinit get_initial_mode(struct intelfb_info *dinfo); | 137 | static void __devinit get_initial_mode(struct intelfb_info *dinfo); |
136 | static void update_dinfo(struct intelfb_info *dinfo, | 138 | static 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 | ||
267 | static __inline__ char * | 271 | static __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 | |||
1467 | intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 1517 | intelfb_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 | ||
43 | struct 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 | |||
55 | static 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 | |||
43 | int | 69 | int |
44 | intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, | 70 | intelfbhw_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 | ||
594 | static 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 | |||
601 | static 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 | |||
618 | static void | ||
619 | intelfbhw_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 | |||
532 | void | 645 | void |
533 | intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | 646 | intelfbhw_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. */ |
699 | static int | 806 | static int |
700 | splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2) | 807 | splitm(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. */ |
720 | static int | 828 | static int |
721 | splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) | 829 | splitp(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 | ||
743 | static int | 863 | static int |
744 | calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | 864 | calc_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 | ||
1718 | void | 1874 | void |
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 */ |
525 | extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, | 505 | extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo); |
526 | int *chipset, int *mobile); | ||
527 | extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | 506 | extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, |
528 | int *stolen_size); | 507 | int *stolen_size); |
529 | extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo); | 508 | extern 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 | ||
225 | int matroxfb_enable_irq(WPMINFO int reenable) { | 227 | int 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) { | |||
390 | static int matroxfb_open(struct fb_info *info, int user) | 392 | static 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) | |||
406 | static int matroxfb_release(struct fb_info *info, int user) | 408 | static 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; |
1903 | failVideoIO:; | 1905 | failVideoIO:; |
@@ -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 | ||
57 | static struct fb_fix_screeninfo maxinefb_fix = { | 57 | static 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 | ||
108 | static struct fb_ops maxinefb_ops = { | 108 | static 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 | |||
7 | nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ | 7 | nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \ |
8 | nv_accel.o | 8 | nv_accel.o |
9 | nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o | 9 | nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o |
10 | nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT) += nv_backlight.o | ||
10 | nvidiafb-$(CONFIG_PPC_OF) += nv_of.o | 11 | nvidiafb-$(CONFIG_PPC_OF) += nv_of.o |
11 | 12 | ||
12 | nvidiafb-objs := $(nvidiafb-y) \ No newline at end of file | 13 | nvidiafb-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 | |||
30 | static struct backlight_properties nvidia_bl_data; | ||
31 | |||
32 | static 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 | |||
53 | static 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 | |||
87 | static int nvidia_bl_get_brightness(struct backlight_device *bd) | ||
88 | { | ||
89 | return bd->props->brightness; | ||
90 | } | ||
91 | |||
92 | static 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 | |||
99 | void 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 | |||
147 | error: | ||
148 | return; | ||
149 | } | ||
150 | |||
151 | void 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); |
64 | extern int nvidiafb_sync(struct fb_info *info); | 64 | extern int nvidiafb_sync(struct fb_info *info); |
65 | extern u8 byte_rev[256]; | 65 | extern u8 byte_rev[256]; |
66 | |||
67 | /* in nv_backlight.h */ | ||
68 | #ifdef CONFIG_FB_NVIDIA_BACKLIGHT | ||
69 | extern void nvidia_bl_init(struct nvidia_par *par); | ||
70 | extern void nvidia_bl_exit(struct nvidia_par *par); | ||
71 | #else | ||
72 | static inline void nvidia_bl_init(struct nvidia_par *par) {} | ||
73 | static 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 | |||
478 | static 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 | |||
503 | static 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 | |||
530 | static int nvidia_set_backlight_level(int level, void *data) | ||
531 | { | ||
532 | return nvidia_set_backlight_enable(1, level, data); | ||
533 | } | ||
534 | |||
535 | static struct backlight_controller nvidia_backlight_controller = { | ||
536 | nvidia_set_backlight_enable, | ||
537 | nvidia_set_backlight_level | ||
538 | }; | ||
539 | |||
540 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
541 | |||
542 | static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8, | 470 | static 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 | ||
277 | static int riva_backlight_levels[] = { | 283 | static struct backlight_properties riva_bl_data; |
278 | 0x158, | 284 | |
279 | 0x192, | 285 | static 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 | |||
306 | static 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 | |||
331 | static int riva_bl_get_brightness(struct backlight_device *bd) | ||
332 | { | ||
333 | return bd->props->brightness; | ||
334 | } | ||
295 | 335 | ||
296 | static int riva_set_backlight_enable(int on, int level, void *data); | 336 | static struct backlight_properties riva_bl_data = { |
297 | static int riva_set_backlight_level(int level, void *data); | 337 | .owner = THIS_MODULE, |
298 | static 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 | |
343 | static 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 | |||
391 | error: | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | static 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 | ||
421 | static inline void riva_bl_init(struct riva_par *par) {} | ||
422 | static 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 | ||
981 | static 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 | |||
998 | static 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 */ |
554 | static int __init get_nativex(void) | 554 | static 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 | */ |
661 | static unsigned int __init get_displaytype(void) | 661 | static 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 */ |
671 | static unsigned int __init get_memsize(void) | 671 | static 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"); |