diff options
author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-29 05:14:30 -0400 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-29 05:14:30 -0400 |
commit | d4a7dbfdf180a656de3eb9e64614e2b991ffaa53 (patch) | |
tree | f7d0d548004751aea77f63e6fd695faf0785bde0 /drivers/video | |
parent | b5480ed72e4f299c53d1857faaf4f492650ccc43 (diff) | |
parent | fa514fbc57419505d0e9423dbb8742f2775f882e (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-3.x into fbdev-next
Conflicts:
drivers/video/atmel_lcdfb.c
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 16 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/au1200fb.c | 297 | ||||
-rw-r--r-- | drivers/video/backlight/adp8860_bl.c | 1 | ||||
-rw-r--r-- | drivers/video/backlight/adp8870_bl.c | 1 | ||||
-rw-r--r-- | drivers/video/carminefb.c | 6 | ||||
-rw-r--r-- | drivers/video/controlfb.c | 2 | ||||
-rw-r--r-- | drivers/video/da8xx-fb.c | 151 | ||||
-rw-r--r-- | drivers/video/fb_defio.c | 3 | ||||
-rw-r--r-- | drivers/video/fsl-diu-fb.c | 74 | ||||
-rw-r--r-- | drivers/video/grvga.c | 579 | ||||
-rw-r--r-- | drivers/video/msm/mdp.c | 4 | ||||
-rw-r--r-- | drivers/video/platinumfb.c | 2 | ||||
-rw-r--r-- | drivers/video/pm2fb.c | 2 | ||||
-rw-r--r-- | drivers/video/pm3fb.c | 2 | ||||
-rw-r--r-- | drivers/video/pxa3xx-gcu.c | 2 | ||||
-rw-r--r-- | drivers/video/s3c2410fb.c | 1 | ||||
-rw-r--r-- | drivers/video/s3fb.c | 2 | ||||
-rw-r--r-- | drivers/video/skeletonfb.c | 2 | ||||
-rw-r--r-- | drivers/video/udlfb.c | 21 | ||||
-rw-r--r-- | drivers/video/valkyriefb.c | 2 | ||||
-rw-r--r-- | drivers/video/via/via_modesetting.h | 5 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.c | 16 | ||||
-rw-r--r-- | drivers/video/xilinxfb.c | 1 |
24 files changed, 966 insertions, 227 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 963b8b767b83..903ace58fec5 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -259,6 +259,15 @@ config FB_TILEBLITTING | |||
259 | comment "Frame buffer hardware drivers" | 259 | comment "Frame buffer hardware drivers" |
260 | depends on FB | 260 | depends on FB |
261 | 261 | ||
262 | config FB_GRVGA | ||
263 | tristate "Aeroflex Gaisler framebuffer support" | ||
264 | depends on FB && SPARC | ||
265 | select FB_CFB_FILLRECT | ||
266 | select FB_CFB_COPYAREA | ||
267 | select FB_CFB_IMAGEBLIT | ||
268 | ---help--- | ||
269 | This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler. | ||
270 | |||
262 | config FB_CIRRUS | 271 | config FB_CIRRUS |
263 | tristate "Cirrus Logic support" | 272 | tristate "Cirrus Logic support" |
264 | depends on FB && (ZORRO || PCI) | 273 | depends on FB && (ZORRO || PCI) |
@@ -1756,9 +1765,10 @@ config FB_AU1100 | |||
1756 | config FB_AU1200 | 1765 | config FB_AU1200 |
1757 | bool "Au1200 LCD Driver" | 1766 | bool "Au1200 LCD Driver" |
1758 | depends on (FB = y) && MIPS && SOC_AU1200 | 1767 | depends on (FB = y) && MIPS && SOC_AU1200 |
1759 | select FB_CFB_FILLRECT | 1768 | select FB_SYS_FILLRECT |
1760 | select FB_CFB_COPYAREA | 1769 | select FB_SYS_COPYAREA |
1761 | select FB_CFB_IMAGEBLIT | 1770 | select FB_SYS_IMAGEBLIT |
1771 | select FB_SYS_FOPS | ||
1762 | help | 1772 | help |
1763 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive | 1773 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive |
1764 | various panels and CRTs by passing in kernel cmd line option | 1774 | various panels and CRTs by passing in kernel cmd line option |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 8b83129e209c..43079108bb16 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o | |||
33 | obj-$(CONFIG_FB_ARC) += arcfb.o | 33 | obj-$(CONFIG_FB_ARC) += arcfb.o |
34 | obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o | 34 | obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o |
35 | obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o | 35 | obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o |
36 | obj-$(CONFIG_FB_GRVGA) += grvga.o | ||
36 | obj-$(CONFIG_FB_PM2) += pm2fb.o | 37 | obj-$(CONFIG_FB_PM2) += pm2fb.o |
37 | obj-$(CONFIG_FB_PM3) += pm3fb.o | 38 | obj-$(CONFIG_FB_PM3) += pm3fb.o |
38 | 39 | ||
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 5dff32ac8044..ed5dcdb29cf7 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c | |||
@@ -46,14 +46,6 @@ | |||
46 | #include <asm/mach-au1x00/au1000.h> | 46 | #include <asm/mach-au1x00/au1000.h> |
47 | #include "au1200fb.h" | 47 | #include "au1200fb.h" |
48 | 48 | ||
49 | #ifdef CONFIG_PM | ||
50 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
51 | #endif | ||
52 | |||
53 | #ifndef CONFIG_FB_AU1200_DEVS | ||
54 | #define CONFIG_FB_AU1200_DEVS 4 | ||
55 | #endif | ||
56 | |||
57 | #define DRIVER_NAME "au1200fb" | 49 | #define DRIVER_NAME "au1200fb" |
58 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" | 50 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" |
59 | 51 | ||
@@ -150,7 +142,7 @@ struct au1200_lcd_iodata_t { | |||
150 | 142 | ||
151 | /* Private, per-framebuffer management information (independent of the panel itself) */ | 143 | /* Private, per-framebuffer management information (independent of the panel itself) */ |
152 | struct au1200fb_device { | 144 | struct au1200fb_device { |
153 | struct fb_info fb_info; /* FB driver info record */ | 145 | struct fb_info *fb_info; /* FB driver info record */ |
154 | 146 | ||
155 | int plane; | 147 | int plane; |
156 | unsigned char* fb_mem; /* FrameBuffer memory map */ | 148 | unsigned char* fb_mem; /* FrameBuffer memory map */ |
@@ -158,7 +150,6 @@ struct au1200fb_device { | |||
158 | dma_addr_t fb_phys; | 150 | dma_addr_t fb_phys; |
159 | }; | 151 | }; |
160 | 152 | ||
161 | static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | ||
162 | /********************************************************************/ | 153 | /********************************************************************/ |
163 | 154 | ||
164 | /* LCD controller restrictions */ | 155 | /* LCD controller restrictions */ |
@@ -171,10 +162,18 @@ static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | |||
171 | /* Default number of visible screen buffer to allocate */ | 162 | /* Default number of visible screen buffer to allocate */ |
172 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 | 163 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 |
173 | 164 | ||
165 | /* Default maximum number of fb devices to create */ | ||
166 | #define MAX_DEVICE_COUNT 4 | ||
167 | |||
168 | /* Default window configuration entry to use (see windows[]) */ | ||
169 | #define DEFAULT_WINDOW_INDEX 2 | ||
170 | |||
174 | /********************************************************************/ | 171 | /********************************************************************/ |
175 | 172 | ||
173 | static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT]; | ||
176 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; | 174 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; |
177 | static int window_index = 2; /* default is zero */ | 175 | static int device_count = MAX_DEVICE_COUNT; |
176 | static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */ | ||
178 | static int panel_index = 2; /* default is zero */ | 177 | static int panel_index = 2; /* default is zero */ |
179 | static struct window_settings *win; | 178 | static struct window_settings *win; |
180 | static struct panel_settings *panel; | 179 | static struct panel_settings *panel; |
@@ -205,12 +204,6 @@ struct window_settings { | |||
205 | extern int board_au1200fb_panel_init (void); | 204 | extern int board_au1200fb_panel_init (void); |
206 | extern int board_au1200fb_panel_shutdown (void); | 205 | extern int board_au1200fb_panel_shutdown (void); |
207 | 206 | ||
208 | #ifdef CONFIG_PM | ||
209 | int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
210 | au1xxx_request_t request, void *data); | ||
211 | au1xxx_power_dev_t *LCD_pm_dev; | ||
212 | #endif | ||
213 | |||
214 | /* | 207 | /* |
215 | * Default window configurations | 208 | * Default window configurations |
216 | */ | 209 | */ |
@@ -652,25 +645,6 @@ static struct panel_settings known_lcd_panels[] = | |||
652 | 645 | ||
653 | /********************************************************************/ | 646 | /********************************************************************/ |
654 | 647 | ||
655 | #ifdef CONFIG_PM | ||
656 | static int set_brightness(unsigned int brightness) | ||
657 | { | ||
658 | unsigned int hi1, divider; | ||
659 | |||
660 | /* limit brightness pwm duty to >= 30/1600 */ | ||
661 | if (brightness < 30) { | ||
662 | brightness = 30; | ||
663 | } | ||
664 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
665 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
666 | hi1 = (((brightness & 0xFF) + 1) * divider >> 8); | ||
667 | lcd->pwmhi &= 0xFFFF; | ||
668 | lcd->pwmhi |= (hi1 << 16); | ||
669 | |||
670 | return brightness; | ||
671 | } | ||
672 | #endif /* CONFIG_PM */ | ||
673 | |||
674 | static int winbpp (unsigned int winctrl1) | 648 | static int winbpp (unsigned int winctrl1) |
675 | { | 649 | { |
676 | int bits = 0; | 650 | int bits = 0; |
@@ -712,8 +686,8 @@ static int fbinfo2index (struct fb_info *fb_info) | |||
712 | { | 686 | { |
713 | int i; | 687 | int i; |
714 | 688 | ||
715 | for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { | 689 | for (i = 0; i < device_count; ++i) { |
716 | if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) | 690 | if (fb_info == _au1200fb_infos[i]) |
717 | return i; | 691 | return i; |
718 | } | 692 | } |
719 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); | 693 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); |
@@ -962,7 +936,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev) | |||
962 | lcd->window[plane].winctrl2 = ( 0 | 936 | lcd->window[plane].winctrl2 = ( 0 |
963 | | LCD_WINCTRL2_CKMODE_00 | 937 | | LCD_WINCTRL2_CKMODE_00 |
964 | | LCD_WINCTRL2_DBM | 938 | | LCD_WINCTRL2_DBM |
965 | | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | 939 | | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length) |
966 | | LCD_WINCTRL2_SCX_1 | 940 | | LCD_WINCTRL2_SCX_1 |
967 | | LCD_WINCTRL2_SCY_1 | 941 | | LCD_WINCTRL2_SCY_1 |
968 | ) ; | 942 | ) ; |
@@ -1050,7 +1024,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi) | |||
1050 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | 1024 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, |
1051 | struct fb_info *fbi) | 1025 | struct fb_info *fbi) |
1052 | { | 1026 | { |
1053 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | 1027 | struct au1200fb_device *fbdev = fbi->par; |
1054 | u32 pixclock; | 1028 | u32 pixclock; |
1055 | int screen_size, plane; | 1029 | int screen_size, plane; |
1056 | 1030 | ||
@@ -1142,7 +1116,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | |||
1142 | */ | 1116 | */ |
1143 | static int au1200fb_fb_set_par(struct fb_info *fbi) | 1117 | static int au1200fb_fb_set_par(struct fb_info *fbi) |
1144 | { | 1118 | { |
1145 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | 1119 | struct au1200fb_device *fbdev = fbi->par; |
1146 | 1120 | ||
1147 | au1200fb_update_fbinfo(fbi); | 1121 | au1200fb_update_fbinfo(fbi); |
1148 | au1200_setmode(fbdev); | 1122 | au1200_setmode(fbdev); |
@@ -1246,11 +1220,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
1246 | { | 1220 | { |
1247 | unsigned int len; | 1221 | unsigned int len; |
1248 | unsigned long start=0, off; | 1222 | unsigned long start=0, off; |
1249 | struct au1200fb_device *fbdev = (struct au1200fb_device *) info; | 1223 | struct au1200fb_device *fbdev = info->par; |
1250 | |||
1251 | #ifdef CONFIG_PM | ||
1252 | au1xxx_pm_access(LCD_pm_dev); | ||
1253 | #endif | ||
1254 | 1224 | ||
1255 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | 1225 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { |
1256 | return -EINVAL; | 1226 | return -EINVAL; |
@@ -1461,10 +1431,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1461 | int plane; | 1431 | int plane; |
1462 | int val; | 1432 | int val; |
1463 | 1433 | ||
1464 | #ifdef CONFIG_PM | ||
1465 | au1xxx_pm_access(LCD_pm_dev); | ||
1466 | #endif | ||
1467 | |||
1468 | plane = fbinfo2index(info); | 1434 | plane = fbinfo2index(info); |
1469 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); | 1435 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); |
1470 | 1436 | ||
@@ -1536,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = { | |||
1536 | .fb_set_par = au1200fb_fb_set_par, | 1502 | .fb_set_par = au1200fb_fb_set_par, |
1537 | .fb_setcolreg = au1200fb_fb_setcolreg, | 1503 | .fb_setcolreg = au1200fb_fb_setcolreg, |
1538 | .fb_blank = au1200fb_fb_blank, | 1504 | .fb_blank = au1200fb_fb_blank, |
1539 | .fb_fillrect = cfb_fillrect, | 1505 | .fb_fillrect = sys_fillrect, |
1540 | .fb_copyarea = cfb_copyarea, | 1506 | .fb_copyarea = sys_copyarea, |
1541 | .fb_imageblit = cfb_imageblit, | 1507 | .fb_imageblit = sys_imageblit, |
1508 | .fb_read = fb_sys_read, | ||
1509 | .fb_write = fb_sys_write, | ||
1542 | .fb_sync = NULL, | 1510 | .fb_sync = NULL, |
1543 | .fb_ioctl = au1200fb_ioctl, | 1511 | .fb_ioctl = au1200fb_ioctl, |
1544 | .fb_mmap = au1200fb_fb_mmap, | 1512 | .fb_mmap = au1200fb_fb_mmap, |
@@ -1561,10 +1529,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) | |||
1561 | 1529 | ||
1562 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | 1530 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) |
1563 | { | 1531 | { |
1564 | struct fb_info *fbi = &fbdev->fb_info; | 1532 | struct fb_info *fbi = fbdev->fb_info; |
1565 | int bpp; | 1533 | int bpp; |
1566 | 1534 | ||
1567 | memset(fbi, 0, sizeof(struct fb_info)); | ||
1568 | fbi->fbops = &au1200fb_fb_ops; | 1535 | fbi->fbops = &au1200fb_fb_ops; |
1569 | 1536 | ||
1570 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); | 1537 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); |
@@ -1623,24 +1590,36 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | |||
1623 | 1590 | ||
1624 | /* AU1200 LCD controller device driver */ | 1591 | /* AU1200 LCD controller device driver */ |
1625 | 1592 | ||
1626 | static int au1200fb_drv_probe(struct platform_device *dev) | 1593 | static int __devinit au1200fb_drv_probe(struct platform_device *dev) |
1627 | { | 1594 | { |
1628 | struct au1200fb_device *fbdev; | 1595 | struct au1200fb_device *fbdev; |
1596 | struct fb_info *fbi = NULL; | ||
1629 | unsigned long page; | 1597 | unsigned long page; |
1630 | int bpp, plane, ret; | 1598 | int bpp, plane, ret, irq; |
1631 | 1599 | ||
1632 | if (!dev) | 1600 | /* shut gcc up */ |
1633 | return -EINVAL; | 1601 | ret = 0; |
1602 | fbdev = NULL; | ||
1603 | |||
1604 | /* Kickstart the panel */ | ||
1605 | au1200_setpanel(panel); | ||
1634 | 1606 | ||
1635 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | 1607 | for (plane = 0; plane < device_count; ++plane) { |
1636 | bpp = winbpp(win->w[plane].mode_winctrl1); | 1608 | bpp = winbpp(win->w[plane].mode_winctrl1); |
1637 | if (win->w[plane].xres == 0) | 1609 | if (win->w[plane].xres == 0) |
1638 | win->w[plane].xres = panel->Xres; | 1610 | win->w[plane].xres = panel->Xres; |
1639 | if (win->w[plane].yres == 0) | 1611 | if (win->w[plane].yres == 0) |
1640 | win->w[plane].yres = panel->Yres; | 1612 | win->w[plane].yres = panel->Yres; |
1641 | 1613 | ||
1642 | fbdev = &_au1200fb_devices[plane]; | 1614 | fbi = framebuffer_alloc(sizeof(struct au1200fb_device), |
1643 | memset(fbdev, 0, sizeof(struct au1200fb_device)); | 1615 | &dev->dev); |
1616 | if (!fbi) | ||
1617 | goto failed; | ||
1618 | |||
1619 | _au1200fb_infos[plane] = fbi; | ||
1620 | fbdev = fbi->par; | ||
1621 | fbdev->fb_info = fbi; | ||
1622 | |||
1644 | fbdev->plane = plane; | 1623 | fbdev->plane = plane; |
1645 | 1624 | ||
1646 | /* Allocate the framebuffer to the maximum screen size */ | 1625 | /* Allocate the framebuffer to the maximum screen size */ |
@@ -1673,30 +1652,31 @@ static int au1200fb_drv_probe(struct platform_device *dev) | |||
1673 | goto failed; | 1652 | goto failed; |
1674 | 1653 | ||
1675 | /* Register new framebuffer */ | 1654 | /* Register new framebuffer */ |
1676 | if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { | 1655 | ret = register_framebuffer(fbi); |
1656 | if (ret < 0) { | ||
1677 | print_err("cannot register new framebuffer"); | 1657 | print_err("cannot register new framebuffer"); |
1678 | goto failed; | 1658 | goto failed; |
1679 | } | 1659 | } |
1680 | 1660 | ||
1681 | au1200fb_fb_set_par(&fbdev->fb_info); | 1661 | au1200fb_fb_set_par(fbi); |
1682 | 1662 | ||
1683 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | 1663 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) |
1684 | if (plane == 0) | 1664 | if (plane == 0) |
1685 | if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { | 1665 | if (fb_prepare_logo(fbi, FB_ROTATE_UR)) { |
1686 | /* Start display and show logo on boot */ | 1666 | /* Start display and show logo on boot */ |
1687 | fb_set_cmap(&fbdev->fb_info.cmap, | 1667 | fb_set_cmap(&fbi->cmap, fbi); |
1688 | &fbdev->fb_info); | 1668 | fb_show_logo(fbi, FB_ROTATE_UR); |
1689 | |||
1690 | fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); | ||
1691 | } | 1669 | } |
1692 | #endif | 1670 | #endif |
1693 | } | 1671 | } |
1694 | 1672 | ||
1695 | /* Now hook interrupt too */ | 1673 | /* Now hook interrupt too */ |
1696 | if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, | 1674 | irq = platform_get_irq(dev, 0); |
1697 | IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) { | 1675 | ret = request_irq(irq, au1200fb_handle_irq, |
1676 | IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev); | ||
1677 | if (ret) { | ||
1698 | print_err("fail to request interrupt line %d (err: %d)", | 1678 | print_err("fail to request interrupt line %d (err: %d)", |
1699 | AU1200_LCD_INT, ret); | 1679 | irq, ret); |
1700 | goto failed; | 1680 | goto failed; |
1701 | } | 1681 | } |
1702 | 1682 | ||
@@ -1705,84 +1685,108 @@ static int au1200fb_drv_probe(struct platform_device *dev) | |||
1705 | failed: | 1685 | failed: |
1706 | /* NOTE: This only does the current plane/window that failed; others are still active */ | 1686 | /* NOTE: This only does the current plane/window that failed; others are still active */ |
1707 | if (fbdev->fb_mem) | 1687 | if (fbdev->fb_mem) |
1708 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | 1688 | dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), |
1709 | fbdev->fb_mem, fbdev->fb_phys); | 1689 | fbdev->fb_mem, fbdev->fb_phys); |
1710 | if (fbdev->fb_info.cmap.len != 0) | 1690 | if (fbi) { |
1711 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | 1691 | if (fbi->cmap.len != 0) |
1712 | if (fbdev->fb_info.pseudo_palette) | 1692 | fb_dealloc_cmap(&fbi->cmap); |
1713 | kfree(fbdev->fb_info.pseudo_palette); | 1693 | kfree(fbi->pseudo_palette); |
1694 | } | ||
1714 | if (plane == 0) | 1695 | if (plane == 0) |
1715 | free_irq(AU1200_LCD_INT, (void*)dev); | 1696 | free_irq(AU1200_LCD_INT, (void*)dev); |
1716 | return ret; | 1697 | return ret; |
1717 | } | 1698 | } |
1718 | 1699 | ||
1719 | static int au1200fb_drv_remove(struct platform_device *dev) | 1700 | static int __devexit au1200fb_drv_remove(struct platform_device *dev) |
1720 | { | 1701 | { |
1721 | struct au1200fb_device *fbdev; | 1702 | struct au1200fb_device *fbdev; |
1703 | struct fb_info *fbi; | ||
1722 | int plane; | 1704 | int plane; |
1723 | 1705 | ||
1724 | if (!dev) | ||
1725 | return -ENODEV; | ||
1726 | |||
1727 | /* Turn off the panel */ | 1706 | /* Turn off the panel */ |
1728 | au1200_setpanel(NULL); | 1707 | au1200_setpanel(NULL); |
1729 | 1708 | ||
1730 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) | 1709 | for (plane = 0; plane < device_count; ++plane) { |
1731 | { | 1710 | fbi = _au1200fb_infos[plane]; |
1732 | fbdev = &_au1200fb_devices[plane]; | 1711 | fbdev = fbi->par; |
1733 | 1712 | ||
1734 | /* Clean up all probe data */ | 1713 | /* Clean up all probe data */ |
1735 | unregister_framebuffer(&fbdev->fb_info); | 1714 | unregister_framebuffer(fbi); |
1736 | if (fbdev->fb_mem) | 1715 | if (fbdev->fb_mem) |
1737 | dma_free_noncoherent(&dev->dev, | 1716 | dma_free_noncoherent(&dev->dev, |
1738 | PAGE_ALIGN(fbdev->fb_len), | 1717 | PAGE_ALIGN(fbdev->fb_len), |
1739 | fbdev->fb_mem, fbdev->fb_phys); | 1718 | fbdev->fb_mem, fbdev->fb_phys); |
1740 | if (fbdev->fb_info.cmap.len != 0) | 1719 | if (fbi->cmap.len != 0) |
1741 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | 1720 | fb_dealloc_cmap(&fbi->cmap); |
1742 | if (fbdev->fb_info.pseudo_palette) | 1721 | kfree(fbi->pseudo_palette); |
1743 | kfree(fbdev->fb_info.pseudo_palette); | 1722 | |
1723 | framebuffer_release(fbi); | ||
1724 | _au1200fb_infos[plane] = NULL; | ||
1744 | } | 1725 | } |
1745 | 1726 | ||
1746 | free_irq(AU1200_LCD_INT, (void *)dev); | 1727 | free_irq(platform_get_irq(dev, 0), (void *)dev); |
1747 | 1728 | ||
1748 | return 0; | 1729 | return 0; |
1749 | } | 1730 | } |
1750 | 1731 | ||
1751 | #ifdef CONFIG_PM | 1732 | #ifdef CONFIG_PM |
1752 | static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) | 1733 | static int au1200fb_drv_suspend(struct device *dev) |
1753 | { | 1734 | { |
1754 | /* TODO */ | 1735 | au1200_setpanel(NULL); |
1736 | |||
1737 | lcd->outmask = 0; | ||
1738 | au_sync(); | ||
1739 | |||
1755 | return 0; | 1740 | return 0; |
1756 | } | 1741 | } |
1757 | 1742 | ||
1758 | static int au1200fb_drv_resume(struct platform_device *dev) | 1743 | static int au1200fb_drv_resume(struct device *dev) |
1759 | { | 1744 | { |
1760 | /* TODO */ | 1745 | struct fb_info *fbi; |
1746 | int i; | ||
1747 | |||
1748 | /* Kickstart the panel */ | ||
1749 | au1200_setpanel(panel); | ||
1750 | |||
1751 | for (i = 0; i < device_count; i++) { | ||
1752 | fbi = _au1200fb_infos[i]; | ||
1753 | au1200fb_fb_set_par(fbi); | ||
1754 | } | ||
1755 | |||
1761 | return 0; | 1756 | return 0; |
1762 | } | 1757 | } |
1758 | |||
1759 | static const struct dev_pm_ops au1200fb_pmops = { | ||
1760 | .suspend = au1200fb_drv_suspend, | ||
1761 | .resume = au1200fb_drv_resume, | ||
1762 | .freeze = au1200fb_drv_suspend, | ||
1763 | .thaw = au1200fb_drv_resume, | ||
1764 | }; | ||
1765 | |||
1766 | #define AU1200FB_PMOPS (&au1200fb_pmops) | ||
1767 | |||
1768 | #else | ||
1769 | #define AU1200FB_PMOPS NULL | ||
1763 | #endif /* CONFIG_PM */ | 1770 | #endif /* CONFIG_PM */ |
1764 | 1771 | ||
1765 | static struct platform_driver au1200fb_driver = { | 1772 | static struct platform_driver au1200fb_driver = { |
1766 | .driver = { | 1773 | .driver = { |
1767 | .name = "au1200-lcd", | 1774 | .name = "au1200-lcd", |
1768 | .owner = THIS_MODULE, | 1775 | .owner = THIS_MODULE, |
1776 | .pm = AU1200FB_PMOPS, | ||
1769 | }, | 1777 | }, |
1770 | .probe = au1200fb_drv_probe, | 1778 | .probe = au1200fb_drv_probe, |
1771 | .remove = au1200fb_drv_remove, | 1779 | .remove = __devexit_p(au1200fb_drv_remove), |
1772 | #ifdef CONFIG_PM | ||
1773 | .suspend = au1200fb_drv_suspend, | ||
1774 | .resume = au1200fb_drv_resume, | ||
1775 | #endif | ||
1776 | }; | 1780 | }; |
1777 | 1781 | ||
1778 | /*-------------------------------------------------------------------------*/ | 1782 | /*-------------------------------------------------------------------------*/ |
1779 | 1783 | ||
1780 | /* Kernel driver */ | 1784 | /* Kernel driver */ |
1781 | 1785 | ||
1782 | static void au1200fb_setup(void) | 1786 | static int au1200fb_setup(void) |
1783 | { | 1787 | { |
1784 | char* options = NULL; | 1788 | char *options = NULL; |
1785 | char* this_opt; | 1789 | char *this_opt, *endptr; |
1786 | int num_panels = ARRAY_SIZE(known_lcd_panels); | 1790 | int num_panels = ARRAY_SIZE(known_lcd_panels); |
1787 | int panel_idx = -1; | 1791 | int panel_idx = -1; |
1788 | 1792 | ||
@@ -1827,70 +1831,42 @@ static void au1200fb_setup(void) | |||
1827 | nohwcursor = 1; | 1831 | nohwcursor = 1; |
1828 | } | 1832 | } |
1829 | 1833 | ||
1830 | /* Unsupported option */ | 1834 | else if (strncmp(this_opt, "devices:", 8) == 0) { |
1831 | else { | 1835 | this_opt += 8; |
1832 | print_warn("Unsupported option \"%s\"", this_opt); | 1836 | device_count = simple_strtol(this_opt, |
1837 | &endptr, 0); | ||
1838 | if ((device_count < 0) || | ||
1839 | (device_count > MAX_DEVICE_COUNT)) | ||
1840 | device_count = MAX_DEVICE_COUNT; | ||
1833 | } | 1841 | } |
1834 | } | ||
1835 | } | ||
1836 | } | ||
1837 | 1842 | ||
1838 | #ifdef CONFIG_PM | 1843 | else if (strncmp(this_opt, "wincfg:", 7) == 0) { |
1839 | static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | 1844 | this_opt += 7; |
1840 | au1xxx_request_t request, void *data) { | 1845 | window_index = simple_strtol(this_opt, |
1841 | int retval = -1; | 1846 | &endptr, 0); |
1842 | unsigned int d = 0; | 1847 | if ((window_index < 0) || |
1843 | unsigned int brightness = 0; | 1848 | (window_index >= ARRAY_SIZE(windows))) |
1844 | 1849 | window_index = DEFAULT_WINDOW_INDEX; | |
1845 | if (request == AU1XXX_PM_SLEEP) { | ||
1846 | board_au1200fb_panel_shutdown(); | ||
1847 | } | ||
1848 | else if (request == AU1XXX_PM_WAKEUP) { | ||
1849 | if(dev->prev_state == SLEEP_STATE) | ||
1850 | { | ||
1851 | int plane; | ||
1852 | au1200_setpanel(panel); | ||
1853 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
1854 | struct au1200fb_device *fbdev; | ||
1855 | fbdev = &_au1200fb_devices[plane]; | ||
1856 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
1857 | } | 1850 | } |
1858 | } | ||
1859 | 1851 | ||
1860 | d = *((unsigned int*)data); | 1852 | else if (strncmp(this_opt, "off", 3) == 0) |
1861 | if(d <=10) brightness = 26; | 1853 | return 1; |
1862 | else if(d<=20) brightness = 51; | 1854 | /* Unsupported option */ |
1863 | else if(d<=30) brightness = 77; | 1855 | else { |
1864 | else if(d<=40) brightness = 102; | 1856 | print_warn("Unsupported option \"%s\"", this_opt); |
1865 | else if(d<=50) brightness = 128; | 1857 | } |
1866 | else if(d<=60) brightness = 153; | ||
1867 | else if(d<=70) brightness = 179; | ||
1868 | else if(d<=80) brightness = 204; | ||
1869 | else if(d<=90) brightness = 230; | ||
1870 | else brightness = 255; | ||
1871 | set_brightness(brightness); | ||
1872 | } else if (request == AU1XXX_PM_GETSTATUS) { | ||
1873 | return dev->cur_state; | ||
1874 | } else if (request == AU1XXX_PM_ACCESS) { | ||
1875 | if (dev->cur_state != SLEEP_STATE) | ||
1876 | return retval; | ||
1877 | else { | ||
1878 | au1200_setpanel(panel); | ||
1879 | } | 1858 | } |
1880 | } else if (request == AU1XXX_PM_IDLE) { | ||
1881 | } else if (request == AU1XXX_PM_CLEANUP) { | ||
1882 | } | 1859 | } |
1883 | 1860 | return 0; | |
1884 | return retval; | ||
1885 | } | 1861 | } |
1886 | #endif | ||
1887 | 1862 | ||
1888 | static int __init au1200fb_init(void) | 1863 | static int __init au1200fb_init(void) |
1889 | { | 1864 | { |
1890 | print_info("" DRIVER_DESC ""); | 1865 | print_info("" DRIVER_DESC ""); |
1891 | 1866 | ||
1892 | /* Setup driver with options */ | 1867 | /* Setup driver with options */ |
1893 | au1200fb_setup(); | 1868 | if (au1200fb_setup()) |
1869 | return -ENODEV; | ||
1894 | 1870 | ||
1895 | /* Point to the panel selected */ | 1871 | /* Point to the panel selected */ |
1896 | panel = &known_lcd_panels[panel_index]; | 1872 | panel = &known_lcd_panels[panel_index]; |
@@ -1899,17 +1875,6 @@ static int __init au1200fb_init(void) | |||
1899 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); | 1875 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); |
1900 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); | 1876 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); |
1901 | 1877 | ||
1902 | /* Kickstart the panel, the framebuffers/windows come soon enough */ | ||
1903 | au1200_setpanel(panel); | ||
1904 | |||
1905 | #ifdef CONFIG_PM | ||
1906 | LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); | ||
1907 | if ( LCD_pm_dev == NULL) | ||
1908 | printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); | ||
1909 | else | ||
1910 | printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); | ||
1911 | #endif | ||
1912 | |||
1913 | return platform_driver_register(&au1200fb_driver); | 1878 | return platform_driver_register(&au1200fb_driver); |
1914 | } | 1879 | } |
1915 | 1880 | ||
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 183b6f639852..66bc74d9ce2a 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c | |||
@@ -7,7 +7,6 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/version.h> | ||
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
13 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 05a8832bb3eb..383c4c364b5f 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c | |||
@@ -7,7 +7,6 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/version.h> | ||
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
13 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index caaa27d4a46a..cb09aa1fa138 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c | |||
@@ -32,11 +32,11 @@ | |||
32 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 | 32 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 |
33 | 33 | ||
34 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; | 34 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; |
35 | module_param(fb_mode, uint, 444); | 35 | module_param(fb_mode, uint, 0444); |
36 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); | 36 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); |
37 | 37 | ||
38 | static char *fb_mode_str; | 38 | static char *fb_mode_str; |
39 | module_param(fb_mode_str, charp, 444); | 39 | module_param(fb_mode_str, charp, 0444); |
40 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | 40 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); |
41 | 41 | ||
42 | /* | 42 | /* |
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | |||
46 | * 0b010 Display 1 | 46 | * 0b010 Display 1 |
47 | */ | 47 | */ |
48 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; | 48 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; |
49 | module_param(fb_displays, int, 444); | 49 | module_param(fb_displays, int, 0444); |
50 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); | 50 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); |
51 | 51 | ||
52 | struct carmine_hw { | 52 | struct carmine_hw { |
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 9075bea55879..7b2c40abae15 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
@@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro | |||
550 | 550 | ||
551 | 551 | ||
552 | /* | 552 | /* |
553 | * Parse user speficied options (`video=controlfb:') | 553 | * Parse user specified options (`video=controlfb:') |
554 | */ | 554 | */ |
555 | static void __init control_setup(char *options) | 555 | static void __init control_setup(char *options) |
556 | { | 556 | { |
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 8d4e4ebd9977..217c05f74541 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
@@ -35,6 +35,9 @@ | |||
35 | 35 | ||
36 | #define DRIVER_NAME "da8xx_lcdc" | 36 | #define DRIVER_NAME "da8xx_lcdc" |
37 | 37 | ||
38 | #define LCD_VERSION_1 1 | ||
39 | #define LCD_VERSION_2 2 | ||
40 | |||
38 | /* LCD Status Register */ | 41 | /* LCD Status Register */ |
39 | #define LCD_END_OF_FRAME1 BIT(9) | 42 | #define LCD_END_OF_FRAME1 BIT(9) |
40 | #define LCD_END_OF_FRAME0 BIT(8) | 43 | #define LCD_END_OF_FRAME0 BIT(8) |
@@ -49,7 +52,9 @@ | |||
49 | #define LCD_DMA_BURST_4 0x2 | 52 | #define LCD_DMA_BURST_4 0x2 |
50 | #define LCD_DMA_BURST_8 0x3 | 53 | #define LCD_DMA_BURST_8 0x3 |
51 | #define LCD_DMA_BURST_16 0x4 | 54 | #define LCD_DMA_BURST_16 0x4 |
52 | #define LCD_END_OF_FRAME_INT_ENA BIT(2) | 55 | #define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) |
56 | #define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) | ||
57 | #define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) | ||
53 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) | 58 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) |
54 | 59 | ||
55 | /* LCD Control Register */ | 60 | /* LCD Control Register */ |
@@ -65,12 +70,18 @@ | |||
65 | #define LCD_MONO_8BIT_MODE BIT(9) | 70 | #define LCD_MONO_8BIT_MODE BIT(9) |
66 | #define LCD_RASTER_ORDER BIT(8) | 71 | #define LCD_RASTER_ORDER BIT(8) |
67 | #define LCD_TFT_MODE BIT(7) | 72 | #define LCD_TFT_MODE BIT(7) |
68 | #define LCD_UNDERFLOW_INT_ENA BIT(6) | 73 | #define LCD_V1_UNDERFLOW_INT_ENA BIT(6) |
69 | #define LCD_PL_ENABLE BIT(4) | 74 | #define LCD_V2_UNDERFLOW_INT_ENA BIT(5) |
75 | #define LCD_V1_PL_INT_ENA BIT(4) | ||
76 | #define LCD_V2_PL_INT_ENA BIT(6) | ||
70 | #define LCD_MONOCHROME_MODE BIT(1) | 77 | #define LCD_MONOCHROME_MODE BIT(1) |
71 | #define LCD_RASTER_ENABLE BIT(0) | 78 | #define LCD_RASTER_ENABLE BIT(0) |
72 | #define LCD_TFT_ALT_ENABLE BIT(23) | 79 | #define LCD_TFT_ALT_ENABLE BIT(23) |
73 | #define LCD_STN_565_ENABLE BIT(24) | 80 | #define LCD_STN_565_ENABLE BIT(24) |
81 | #define LCD_V2_DMA_CLK_EN BIT(2) | ||
82 | #define LCD_V2_LIDD_CLK_EN BIT(1) | ||
83 | #define LCD_V2_CORE_CLK_EN BIT(0) | ||
84 | #define LCD_V2_LPP_B10 26 | ||
74 | 85 | ||
75 | /* LCD Raster Timing 2 Register */ | 86 | /* LCD Raster Timing 2 Register */ |
76 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) | 87 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) |
@@ -82,6 +93,7 @@ | |||
82 | #define LCD_INVERT_FRAME_CLOCK BIT(20) | 93 | #define LCD_INVERT_FRAME_CLOCK BIT(20) |
83 | 94 | ||
84 | /* LCD Block */ | 95 | /* LCD Block */ |
96 | #define LCD_PID_REG 0x0 | ||
85 | #define LCD_CTRL_REG 0x4 | 97 | #define LCD_CTRL_REG 0x4 |
86 | #define LCD_STAT_REG 0x8 | 98 | #define LCD_STAT_REG 0x8 |
87 | #define LCD_RASTER_CTRL_REG 0x28 | 99 | #define LCD_RASTER_CTRL_REG 0x28 |
@@ -94,6 +106,17 @@ | |||
94 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C | 106 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C |
95 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 | 107 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 |
96 | 108 | ||
109 | /* Interrupt Registers available only in Version 2 */ | ||
110 | #define LCD_RAW_STAT_REG 0x58 | ||
111 | #define LCD_MASKED_STAT_REG 0x5c | ||
112 | #define LCD_INT_ENABLE_SET_REG 0x60 | ||
113 | #define LCD_INT_ENABLE_CLR_REG 0x64 | ||
114 | #define LCD_END_OF_INT_IND_REG 0x68 | ||
115 | |||
116 | /* Clock registers available only on Version 2 */ | ||
117 | #define LCD_CLK_ENABLE_REG 0x6c | ||
118 | #define LCD_CLK_RESET_REG 0x70 | ||
119 | |||
97 | #define LCD_NUM_BUFFERS 2 | 120 | #define LCD_NUM_BUFFERS 2 |
98 | 121 | ||
99 | #define WSI_TIMEOUT 50 | 122 | #define WSI_TIMEOUT 50 |
@@ -105,6 +128,8 @@ | |||
105 | 128 | ||
106 | static resource_size_t da8xx_fb_reg_base; | 129 | static resource_size_t da8xx_fb_reg_base; |
107 | static struct resource *lcdc_regs; | 130 | static struct resource *lcdc_regs; |
131 | static unsigned int lcd_revision; | ||
132 | static irq_handler_t lcdc_irq_handler; | ||
108 | 133 | ||
109 | static inline unsigned int lcdc_read(unsigned int addr) | 134 | static inline unsigned int lcdc_read(unsigned int addr) |
110 | { | 135 | { |
@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
240 | u32 end; | 265 | u32 end; |
241 | u32 reg_ras; | 266 | u32 reg_ras; |
242 | u32 reg_dma; | 267 | u32 reg_dma; |
268 | u32 reg_int; | ||
243 | 269 | ||
244 | /* init reg to clear PLM (loading mode) fields */ | 270 | /* init reg to clear PLM (loading mode) fields */ |
245 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 271 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
252 | end = par->dma_end; | 278 | end = par->dma_end; |
253 | 279 | ||
254 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); | 280 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); |
255 | reg_dma |= LCD_END_OF_FRAME_INT_ENA; | 281 | if (lcd_revision == LCD_VERSION_1) { |
282 | reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; | ||
283 | } else { | ||
284 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
285 | LCD_V2_END_OF_FRAME0_INT_ENA | | ||
286 | LCD_V2_END_OF_FRAME1_INT_ENA; | ||
287 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
288 | } | ||
256 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; | 289 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; |
257 | 290 | ||
258 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 291 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
264 | end = start + par->palette_sz - 1; | 297 | end = start + par->palette_sz - 1; |
265 | 298 | ||
266 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); | 299 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); |
267 | reg_ras |= LCD_PL_ENABLE; | 300 | |
301 | if (lcd_revision == LCD_VERSION_1) { | ||
302 | reg_ras |= LCD_V1_PL_INT_ENA; | ||
303 | } else { | ||
304 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
305 | LCD_V2_PL_INT_ENA; | ||
306 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
307 | } | ||
268 | 308 | ||
269 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 309 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
270 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 310 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, | |||
348 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | 388 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) |
349 | { | 389 | { |
350 | u32 reg; | 390 | u32 reg; |
391 | u32 reg_int; | ||
351 | 392 | ||
352 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | | 393 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | |
353 | LCD_MONO_8BIT_MODE | | 394 | LCD_MONO_8BIT_MODE | |
@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
375 | } | 416 | } |
376 | 417 | ||
377 | /* enable additional interrupts here */ | 418 | /* enable additional interrupts here */ |
378 | reg |= LCD_UNDERFLOW_INT_ENA; | 419 | if (lcd_revision == LCD_VERSION_1) { |
420 | reg |= LCD_V1_UNDERFLOW_INT_ENA; | ||
421 | } else { | ||
422 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
423 | LCD_V2_UNDERFLOW_INT_ENA; | ||
424 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
425 | } | ||
379 | 426 | ||
380 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | 427 | lcdc_write(reg, LCD_RASTER_CTRL_REG); |
381 | 428 | ||
@@ -511,6 +558,9 @@ static void lcd_reset(struct da8xx_fb_par *par) | |||
511 | /* DMA has to be disabled */ | 558 | /* DMA has to be disabled */ |
512 | lcdc_write(0, LCD_DMA_CTRL_REG); | 559 | lcdc_write(0, LCD_DMA_CTRL_REG); |
513 | lcdc_write(0, LCD_RASTER_CTRL_REG); | 560 | lcdc_write(0, LCD_RASTER_CTRL_REG); |
561 | |||
562 | if (lcd_revision == LCD_VERSION_2) | ||
563 | lcdc_write(0, LCD_INT_ENABLE_SET_REG); | ||
514 | } | 564 | } |
515 | 565 | ||
516 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | 566 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) |
@@ -523,6 +573,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | |||
523 | /* Configure the LCD clock divisor. */ | 573 | /* Configure the LCD clock divisor. */ |
524 | lcdc_write(LCD_CLK_DIVISOR(div) | | 574 | lcdc_write(LCD_CLK_DIVISOR(div) | |
525 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); | 575 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); |
576 | |||
577 | if (lcd_revision == LCD_VERSION_2) | ||
578 | lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | | ||
579 | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); | ||
580 | |||
526 | } | 581 | } |
527 | 582 | ||
528 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | 583 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, |
@@ -583,7 +638,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
583 | return 0; | 638 | return 0; |
584 | } | 639 | } |
585 | 640 | ||
586 | static irqreturn_t lcdc_irq_handler(int irq, void *arg) | 641 | /* IRQ handler for version 2 of LCDC */ |
642 | static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | ||
643 | { | ||
644 | struct da8xx_fb_par *par = arg; | ||
645 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); | ||
646 | u32 reg_int; | ||
647 | |||
648 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | ||
649 | lcd_disable_raster(); | ||
650 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
651 | lcd_enable_raster(); | ||
652 | } else if (stat & LCD_PL_LOAD_DONE) { | ||
653 | /* | ||
654 | * Must disable raster before changing state of any control bit. | ||
655 | * And also must be disabled before clearing the PL loading | ||
656 | * interrupt via the following write to the status register. If | ||
657 | * this is done after then one gets multiple PL done interrupts. | ||
658 | */ | ||
659 | lcd_disable_raster(); | ||
660 | |||
661 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
662 | |||
663 | /* Disable PL completion inerrupt */ | ||
664 | reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | | ||
665 | (LCD_V2_PL_INT_ENA); | ||
666 | lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); | ||
667 | |||
668 | /* Setup and start data loading mode */ | ||
669 | lcd_blit(LOAD_DATA, par); | ||
670 | } else { | ||
671 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
672 | |||
673 | if (stat & LCD_END_OF_FRAME0) { | ||
674 | lcdc_write(par->dma_start, | ||
675 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
676 | lcdc_write(par->dma_end, | ||
677 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
678 | par->vsync_flag = 1; | ||
679 | wake_up_interruptible(&par->vsync_wait); | ||
680 | } | ||
681 | |||
682 | if (stat & LCD_END_OF_FRAME1) { | ||
683 | lcdc_write(par->dma_start, | ||
684 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | ||
685 | lcdc_write(par->dma_end, | ||
686 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | ||
687 | par->vsync_flag = 1; | ||
688 | wake_up_interruptible(&par->vsync_wait); | ||
689 | } | ||
690 | } | ||
691 | |||
692 | lcdc_write(0, LCD_END_OF_INT_IND_REG); | ||
693 | return IRQ_HANDLED; | ||
694 | } | ||
695 | |||
696 | /* IRQ handler for version 1 LCDC */ | ||
697 | static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) | ||
587 | { | 698 | { |
588 | struct da8xx_fb_par *par = arg; | 699 | struct da8xx_fb_par *par = arg; |
589 | u32 stat = lcdc_read(LCD_STAT_REG); | 700 | u32 stat = lcdc_read(LCD_STAT_REG); |
@@ -606,7 +717,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg) | |||
606 | 717 | ||
607 | /* Disable PL completion inerrupt */ | 718 | /* Disable PL completion inerrupt */ |
608 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 719 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
609 | reg_ras &= ~LCD_PL_ENABLE; | 720 | reg_ras &= ~LCD_V1_PL_INT_ENA; |
610 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); | 721 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); |
611 | 722 | ||
612 | /* Setup and start data loading mode */ | 723 | /* Setup and start data loading mode */ |
@@ -945,6 +1056,22 @@ static int __devinit fb_probe(struct platform_device *device) | |||
945 | if (ret) | 1056 | if (ret) |
946 | goto err_clk_put; | 1057 | goto err_clk_put; |
947 | 1058 | ||
1059 | /* Determine LCD IP Version */ | ||
1060 | switch (lcdc_read(LCD_PID_REG)) { | ||
1061 | case 0x4C100102: | ||
1062 | lcd_revision = LCD_VERSION_1; | ||
1063 | break; | ||
1064 | case 0x4F200800: | ||
1065 | lcd_revision = LCD_VERSION_2; | ||
1066 | break; | ||
1067 | default: | ||
1068 | dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " | ||
1069 | "defaulting to LCD revision 1\n", | ||
1070 | lcdc_read(LCD_PID_REG)); | ||
1071 | lcd_revision = LCD_VERSION_1; | ||
1072 | break; | ||
1073 | } | ||
1074 | |||
948 | for (i = 0, lcdc_info = known_lcd_panels; | 1075 | for (i = 0, lcdc_info = known_lcd_panels; |
949 | i < ARRAY_SIZE(known_lcd_panels); | 1076 | i < ARRAY_SIZE(known_lcd_panels); |
950 | i++, lcdc_info++) { | 1077 | i++, lcdc_info++) { |
@@ -1085,7 +1212,13 @@ static int __devinit fb_probe(struct platform_device *device) | |||
1085 | } | 1212 | } |
1086 | #endif | 1213 | #endif |
1087 | 1214 | ||
1088 | ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); | 1215 | if (lcd_revision == LCD_VERSION_1) |
1216 | lcdc_irq_handler = lcdc_irq_handler_rev01; | ||
1217 | else | ||
1218 | lcdc_irq_handler = lcdc_irq_handler_rev02; | ||
1219 | |||
1220 | ret = request_irq(par->irq, lcdc_irq_handler, 0, | ||
1221 | DRIVER_NAME, par); | ||
1089 | if (ret) | 1222 | if (ret) |
1090 | goto irq_freq; | 1223 | goto irq_freq; |
1091 | return 0; | 1224 | return 0; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 32814e8800e0..c27e153d8882 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -223,8 +223,7 @@ void fb_deferred_io_cleanup(struct fb_info *info) | |||
223 | int i; | 223 | int i; |
224 | 224 | ||
225 | BUG_ON(!fbdefio); | 225 | BUG_ON(!fbdefio); |
226 | cancel_delayed_work(&info->deferred_work); | 226 | cancel_delayed_work_sync(&info->deferred_work); |
227 | flush_scheduled_work(); | ||
228 | 227 | ||
229 | /* clear out the mapping that we setup */ | 228 | /* clear out the mapping that we setup */ |
230 | for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { | 229 | for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0acc7d65aeaa..0f1933b54596 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
33 | 33 | ||
34 | #include <linux/of_platform.h> | ||
35 | |||
36 | #include <sysdev/fsl_soc.h> | 34 | #include <sysdev/fsl_soc.h> |
37 | #include <linux/fsl-diu-fb.h> | 35 | #include <linux/fsl-diu-fb.h> |
38 | #include "edid.h" | 36 | #include "edid.h" |
@@ -183,7 +181,8 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
183 | 181 | ||
184 | static char *fb_mode = "1024x768-32@60"; | 182 | static char *fb_mode = "1024x768-32@60"; |
185 | static unsigned long default_bpp = 32; | 183 | static unsigned long default_bpp = 32; |
186 | static int monitor_port; | 184 | static enum fsl_diu_monitor_port monitor_port; |
185 | static char *monitor_string; | ||
187 | 186 | ||
188 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 187 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
189 | static u8 *coherence_data; | 188 | static u8 *coherence_data; |
@@ -201,7 +200,7 @@ struct fsl_diu_data { | |||
201 | void *dummy_aoi_virt; | 200 | void *dummy_aoi_virt; |
202 | unsigned int irq; | 201 | unsigned int irq; |
203 | int fb_enabled; | 202 | int fb_enabled; |
204 | int monitor_port; | 203 | enum fsl_diu_monitor_port monitor_port; |
205 | }; | 204 | }; |
206 | 205 | ||
207 | struct mfb_info { | 206 | struct mfb_info { |
@@ -282,6 +281,37 @@ static struct diu_hw dr = { | |||
282 | static struct diu_pool pool; | 281 | static struct diu_pool pool; |
283 | 282 | ||
284 | /** | 283 | /** |
284 | * fsl_diu_name_to_port - convert a port name to a monitor port enum | ||
285 | * | ||
286 | * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns | ||
287 | * the enum fsl_diu_monitor_port that corresponds to that string. | ||
288 | * | ||
289 | * For compatibility with older versions, a number ("0", "1", or "2") is also | ||
290 | * supported. | ||
291 | * | ||
292 | * If the string is unknown, DVI is assumed. | ||
293 | * | ||
294 | * If the particular port is not supported by the platform, another port | ||
295 | * (platform-specific) is chosen instead. | ||
296 | */ | ||
297 | static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s) | ||
298 | { | ||
299 | enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI; | ||
300 | unsigned long val; | ||
301 | |||
302 | if (s) { | ||
303 | if (!strict_strtoul(s, 10, &val) && (val <= 2)) | ||
304 | port = (enum fsl_diu_monitor_port) val; | ||
305 | else if (strncmp(s, "lvds", 4) == 0) | ||
306 | port = FSL_DIU_PORT_LVDS; | ||
307 | else if (strncmp(s, "dlvds", 5) == 0) | ||
308 | port = FSL_DIU_PORT_DLVDS; | ||
309 | } | ||
310 | |||
311 | return diu_ops.valid_monitor_port(port); | ||
312 | } | ||
313 | |||
314 | /** | ||
285 | * fsl_diu_alloc - allocate memory for the DIU | 315 | * fsl_diu_alloc - allocate memory for the DIU |
286 | * @size: number of bytes to allocate | 316 | * @size: number of bytes to allocate |
287 | * @param: returned physical address of memory | 317 | * @param: returned physical address of memory |
@@ -831,9 +861,8 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
831 | } | 861 | } |
832 | } | 862 | } |
833 | 863 | ||
834 | ad->pix_fmt = | 864 | ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port, |
835 | diu_ops.get_pixel_format(var->bits_per_pixel, | 865 | var->bits_per_pixel); |
836 | machine_data->monitor_port); | ||
837 | ad->addr = cpu_to_le32(info->fix.smem_start); | 866 | ad->addr = cpu_to_le32(info->fix.smem_start); |
838 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | | 867 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | |
839 | var->xres_virtual) | mfbi->g_alpha; | 868 | var->xres_virtual) | mfbi->g_alpha; |
@@ -1439,16 +1468,12 @@ static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, | |||
1439 | static ssize_t store_monitor(struct device *device, | 1468 | static ssize_t store_monitor(struct device *device, |
1440 | struct device_attribute *attr, const char *buf, size_t count) | 1469 | struct device_attribute *attr, const char *buf, size_t count) |
1441 | { | 1470 | { |
1442 | int old_monitor_port; | 1471 | enum fsl_diu_monitor_port old_monitor_port; |
1443 | unsigned long val; | ||
1444 | struct fsl_diu_data *machine_data = | 1472 | struct fsl_diu_data *machine_data = |
1445 | container_of(attr, struct fsl_diu_data, dev_attr); | 1473 | container_of(attr, struct fsl_diu_data, dev_attr); |
1446 | 1474 | ||
1447 | if (strict_strtoul(buf, 10, &val)) | ||
1448 | return 0; | ||
1449 | |||
1450 | old_monitor_port = machine_data->monitor_port; | 1475 | old_monitor_port = machine_data->monitor_port; |
1451 | machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); | 1476 | machine_data->monitor_port = fsl_diu_name_to_port(buf); |
1452 | 1477 | ||
1453 | if (old_monitor_port != machine_data->monitor_port) { | 1478 | if (old_monitor_port != machine_data->monitor_port) { |
1454 | /* All AOIs need adjust pixel format | 1479 | /* All AOIs need adjust pixel format |
@@ -1468,7 +1493,17 @@ static ssize_t show_monitor(struct device *device, | |||
1468 | { | 1493 | { |
1469 | struct fsl_diu_data *machine_data = | 1494 | struct fsl_diu_data *machine_data = |
1470 | container_of(attr, struct fsl_diu_data, dev_attr); | 1495 | container_of(attr, struct fsl_diu_data, dev_attr); |
1471 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); | 1496 | |
1497 | switch (machine_data->monitor_port) { | ||
1498 | case FSL_DIU_PORT_DVI: | ||
1499 | return sprintf(buf, "DVI\n"); | ||
1500 | case FSL_DIU_PORT_LVDS: | ||
1501 | return sprintf(buf, "Single-link LVDS\n"); | ||
1502 | case FSL_DIU_PORT_DLVDS: | ||
1503 | return sprintf(buf, "Dual-link LVDS\n"); | ||
1504 | } | ||
1505 | |||
1506 | return 0; | ||
1472 | } | 1507 | } |
1473 | 1508 | ||
1474 | static int __devinit fsl_diu_probe(struct platform_device *ofdev) | 1509 | static int __devinit fsl_diu_probe(struct platform_device *ofdev) |
@@ -1692,8 +1727,7 @@ static int __init fsl_diu_setup(char *options) | |||
1692 | if (!*opt) | 1727 | if (!*opt) |
1693 | continue; | 1728 | continue; |
1694 | if (!strncmp(opt, "monitor=", 8)) { | 1729 | if (!strncmp(opt, "monitor=", 8)) { |
1695 | if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) | 1730 | monitor_port = fsl_diu_name_to_port(opt + 8); |
1696 | monitor_port = val; | ||
1697 | } else if (!strncmp(opt, "bpp=", 4)) { | 1731 | } else if (!strncmp(opt, "bpp=", 4)) { |
1698 | if (!strict_strtoul(opt + 4, 10, &val)) | 1732 | if (!strict_strtoul(opt + 4, 10, &val)) |
1699 | default_bpp = val; | 1733 | default_bpp = val; |
@@ -1746,6 +1780,8 @@ static int __init fsl_diu_init(void) | |||
1746 | if (fb_get_options("fslfb", &option)) | 1780 | if (fb_get_options("fslfb", &option)) |
1747 | return -ENODEV; | 1781 | return -ENODEV; |
1748 | fsl_diu_setup(option); | 1782 | fsl_diu_setup(option); |
1783 | #else | ||
1784 | monitor_port = fsl_diu_name_to_port(monitor_string); | ||
1749 | #endif | 1785 | #endif |
1750 | printk(KERN_INFO "Freescale DIU driver\n"); | 1786 | printk(KERN_INFO "Freescale DIU driver\n"); |
1751 | 1787 | ||
@@ -1812,7 +1848,7 @@ MODULE_PARM_DESC(mode, | |||
1812 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); | 1848 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); |
1813 | module_param_named(bpp, default_bpp, ulong, 0); | 1849 | module_param_named(bpp, default_bpp, ulong, 0); |
1814 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); | 1850 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); |
1815 | module_param_named(monitor, monitor_port, int, 0); | 1851 | module_param_named(monitor, monitor_string, charp, 0); |
1816 | MODULE_PARM_DESC(monitor, | 1852 | MODULE_PARM_DESC(monitor, "Specify the monitor port " |
1817 | "Specify the monitor port (0, 1 or 2) if supported by the platform"); | 1853 | "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform"); |
1818 | 1854 | ||
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c new file mode 100644 index 000000000000..f37e02538203 --- /dev/null +++ b/drivers/video/grvga.c | |||
@@ -0,0 +1,579 @@ | |||
1 | /* | ||
2 | * Driver for Aeroflex Gaisler SVGACTRL framebuffer device. | ||
3 | * | ||
4 | * 2011 (c) Aeroflex Gaisler AB | ||
5 | * | ||
6 | * Full documentation of the core can be found here: | ||
7 | * http://www.gaisler.com/products/grlib/grip.pdf | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * Contributors: Kristoffer Glembo <kristoffer@gaisler.com> | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/fb.h> | ||
32 | #include <linux/io.h> | ||
33 | |||
34 | struct grvga_regs { | ||
35 | u32 status; /* 0x00 */ | ||
36 | u32 video_length; /* 0x04 */ | ||
37 | u32 front_porch; /* 0x08 */ | ||
38 | u32 sync_length; /* 0x0C */ | ||
39 | u32 line_length; /* 0x10 */ | ||
40 | u32 fb_pos; /* 0x14 */ | ||
41 | u32 clk_vector[4]; /* 0x18 */ | ||
42 | u32 clut; /* 0x20 */ | ||
43 | }; | ||
44 | |||
45 | struct grvga_par { | ||
46 | struct grvga_regs *regs; | ||
47 | u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */ | ||
48 | int clk_sel; | ||
49 | int fb_alloced; /* = 1 if framebuffer is allocated in main memory */ | ||
50 | }; | ||
51 | |||
52 | |||
53 | static const struct fb_videomode grvga_modedb[] = { | ||
54 | { | ||
55 | /* 640x480 @ 60 Hz */ | ||
56 | NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2, | ||
57 | 0, FB_VMODE_NONINTERLACED | ||
58 | }, { | ||
59 | /* 800x600 @ 60 Hz */ | ||
60 | NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, | ||
61 | 0, FB_VMODE_NONINTERLACED | ||
62 | }, { | ||
63 | /* 800x600 @ 72 Hz */ | ||
64 | NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, | ||
65 | 0, FB_VMODE_NONINTERLACED | ||
66 | }, { | ||
67 | /* 1024x768 @ 60 Hz */ | ||
68 | NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, | ||
69 | 0, FB_VMODE_NONINTERLACED | ||
70 | } | ||
71 | }; | ||
72 | |||
73 | static struct fb_fix_screeninfo grvga_fix __initdata = { | ||
74 | .id = "AG SVGACTRL", | ||
75 | .type = FB_TYPE_PACKED_PIXELS, | ||
76 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
77 | .xpanstep = 0, | ||
78 | .ypanstep = 1, | ||
79 | .ywrapstep = 0, | ||
80 | .accel = FB_ACCEL_NONE, | ||
81 | }; | ||
82 | |||
83 | static int grvga_check_var(struct fb_var_screeninfo *var, | ||
84 | struct fb_info *info) | ||
85 | { | ||
86 | struct grvga_par *par = info->par; | ||
87 | int i; | ||
88 | |||
89 | if (!var->xres) | ||
90 | var->xres = 1; | ||
91 | if (!var->yres) | ||
92 | var->yres = 1; | ||
93 | if (var->bits_per_pixel <= 8) | ||
94 | var->bits_per_pixel = 8; | ||
95 | else if (var->bits_per_pixel <= 16) | ||
96 | var->bits_per_pixel = 16; | ||
97 | else if (var->bits_per_pixel <= 24) | ||
98 | var->bits_per_pixel = 24; | ||
99 | else if (var->bits_per_pixel <= 32) | ||
100 | var->bits_per_pixel = 32; | ||
101 | else | ||
102 | return -EINVAL; | ||
103 | |||
104 | var->xres_virtual = var->xres; | ||
105 | var->yres_virtual = 2*var->yres; | ||
106 | |||
107 | if (info->fix.smem_len) { | ||
108 | if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len) | ||
109 | return -ENOMEM; | ||
110 | } | ||
111 | |||
112 | /* Which clocks that are available can be read out in these registers */ | ||
113 | for (i = 0; i <= 3 ; i++) { | ||
114 | if (var->pixclock == par->regs->clk_vector[i]) | ||
115 | break; | ||
116 | } | ||
117 | if (i <= 3) | ||
118 | par->clk_sel = i; | ||
119 | else | ||
120 | return -EINVAL; | ||
121 | |||
122 | switch (info->var.bits_per_pixel) { | ||
123 | case 8: | ||
124 | var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */ | ||
125 | var->green = (struct fb_bitfield) {0, 8, 0}; | ||
126 | var->blue = (struct fb_bitfield) {0, 8, 0}; | ||
127 | var->transp = (struct fb_bitfield) {0, 0, 0}; | ||
128 | break; | ||
129 | case 16: | ||
130 | var->red = (struct fb_bitfield) {11, 5, 0}; | ||
131 | var->green = (struct fb_bitfield) {5, 6, 0}; | ||
132 | var->blue = (struct fb_bitfield) {0, 5, 0}; | ||
133 | var->transp = (struct fb_bitfield) {0, 0, 0}; | ||
134 | break; | ||
135 | case 24: | ||
136 | case 32: | ||
137 | var->red = (struct fb_bitfield) {16, 8, 0}; | ||
138 | var->green = (struct fb_bitfield) {8, 8, 0}; | ||
139 | var->blue = (struct fb_bitfield) {0, 8, 0}; | ||
140 | var->transp = (struct fb_bitfield) {24, 8, 0}; | ||
141 | break; | ||
142 | default: | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int grvga_set_par(struct fb_info *info) | ||
150 | { | ||
151 | |||
152 | u32 func = 0; | ||
153 | struct grvga_par *par = info->par; | ||
154 | |||
155 | __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1), | ||
156 | &par->regs->video_length); | ||
157 | |||
158 | __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin), | ||
159 | &par->regs->front_porch); | ||
160 | |||
161 | __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len), | ||
162 | &par->regs->sync_length); | ||
163 | |||
164 | __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) | | ||
165 | (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1), | ||
166 | &par->regs->line_length); | ||
167 | |||
168 | switch (info->var.bits_per_pixel) { | ||
169 | case 8: | ||
170 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
171 | func = 1; | ||
172 | break; | ||
173 | case 16: | ||
174 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
175 | func = 2; | ||
176 | break; | ||
177 | case 24: | ||
178 | case 32: | ||
179 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
180 | func = 3; | ||
181 | break; | ||
182 | default: | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | |||
186 | __raw_writel((par->clk_sel << 6) | (func << 4) | 1, | ||
187 | &par->regs->status); | ||
188 | |||
189 | info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) | ||
194 | { | ||
195 | struct grvga_par *par; | ||
196 | par = info->par; | ||
197 | |||
198 | if (regno >= 256) /* Size of CLUT */ | ||
199 | return -EINVAL; | ||
200 | |||
201 | if (info->var.grayscale) { | ||
202 | /* grayscale = 0.30*R + 0.59*G + 0.11*B */ | ||
203 | red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; | ||
204 | } | ||
205 | |||
206 | |||
207 | |||
208 | #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) | ||
209 | |||
210 | red = CNVT_TOHW(red, info->var.red.length); | ||
211 | green = CNVT_TOHW(green, info->var.green.length); | ||
212 | blue = CNVT_TOHW(blue, info->var.blue.length); | ||
213 | transp = CNVT_TOHW(transp, info->var.transp.length); | ||
214 | |||
215 | #undef CNVT_TOHW | ||
216 | |||
217 | /* In PSEUDOCOLOR we use the hardware CLUT */ | ||
218 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) | ||
219 | __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue, | ||
220 | &par->regs->clut); | ||
221 | |||
222 | /* Truecolor uses the pseudo palette */ | ||
223 | else if (info->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
224 | u32 v; | ||
225 | if (regno >= 16) | ||
226 | return -EINVAL; | ||
227 | |||
228 | |||
229 | v = (red << info->var.red.offset) | | ||
230 | (green << info->var.green.offset) | | ||
231 | (blue << info->var.blue.offset) | | ||
232 | (transp << info->var.transp.offset); | ||
233 | |||
234 | ((u32 *) (info->pseudo_palette))[regno] = v; | ||
235 | } | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int grvga_pan_display(struct fb_var_screeninfo *var, | ||
240 | struct fb_info *info) | ||
241 | { | ||
242 | struct grvga_par *par = info->par; | ||
243 | struct fb_fix_screeninfo *fix = &info->fix; | ||
244 | u32 base_addr; | ||
245 | |||
246 | if (var->xoffset != 0) | ||
247 | return -EINVAL; | ||
248 | |||
249 | base_addr = fix->smem_start + (var->yoffset * fix->line_length); | ||
250 | base_addr &= ~3UL; | ||
251 | |||
252 | /* Set framebuffer base address */ | ||
253 | __raw_writel(base_addr, | ||
254 | &par->regs->fb_pos); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static struct fb_ops grvga_ops = { | ||
260 | .owner = THIS_MODULE, | ||
261 | .fb_check_var = grvga_check_var, | ||
262 | .fb_set_par = grvga_set_par, | ||
263 | .fb_setcolreg = grvga_setcolreg, | ||
264 | .fb_pan_display = grvga_pan_display, | ||
265 | .fb_fillrect = cfb_fillrect, | ||
266 | .fb_copyarea = cfb_copyarea, | ||
267 | .fb_imageblit = cfb_imageblit | ||
268 | }; | ||
269 | |||
270 | static int __init grvga_parse_custom(char *options, | ||
271 | struct fb_var_screeninfo *screendata) | ||
272 | { | ||
273 | char *this_opt; | ||
274 | int count = 0; | ||
275 | if (!options || !*options) | ||
276 | return -1; | ||
277 | |||
278 | while ((this_opt = strsep(&options, " ")) != NULL) { | ||
279 | if (!*this_opt) | ||
280 | continue; | ||
281 | |||
282 | switch (count) { | ||
283 | case 0: | ||
284 | screendata->pixclock = simple_strtoul(this_opt, NULL, 0); | ||
285 | count++; | ||
286 | break; | ||
287 | case 1: | ||
288 | screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0); | ||
289 | count++; | ||
290 | break; | ||
291 | case 2: | ||
292 | screendata->right_margin = simple_strtoul(this_opt, NULL, 0); | ||
293 | count++; | ||
294 | break; | ||
295 | case 3: | ||
296 | screendata->hsync_len = simple_strtoul(this_opt, NULL, 0); | ||
297 | count++; | ||
298 | break; | ||
299 | case 4: | ||
300 | screendata->left_margin = simple_strtoul(this_opt, NULL, 0); | ||
301 | count++; | ||
302 | break; | ||
303 | case 5: | ||
304 | screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0); | ||
305 | count++; | ||
306 | break; | ||
307 | case 6: | ||
308 | screendata->lower_margin = simple_strtoul(this_opt, NULL, 0); | ||
309 | count++; | ||
310 | break; | ||
311 | case 7: | ||
312 | screendata->vsync_len = simple_strtoul(this_opt, NULL, 0); | ||
313 | count++; | ||
314 | break; | ||
315 | case 8: | ||
316 | screendata->upper_margin = simple_strtoul(this_opt, NULL, 0); | ||
317 | count++; | ||
318 | break; | ||
319 | case 9: | ||
320 | screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0); | ||
321 | count++; | ||
322 | break; | ||
323 | default: | ||
324 | return -1; | ||
325 | } | ||
326 | } | ||
327 | screendata->activate = FB_ACTIVATE_NOW; | ||
328 | screendata->vmode = FB_VMODE_NONINTERLACED; | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int __devinit grvga_probe(struct platform_device *dev) | ||
333 | { | ||
334 | struct fb_info *info; | ||
335 | int retval = -ENOMEM; | ||
336 | unsigned long virtual_start; | ||
337 | unsigned long grvga_fix_addr = 0; | ||
338 | unsigned long physical_start = 0; | ||
339 | unsigned long grvga_mem_size = 0; | ||
340 | struct grvga_par *par = NULL; | ||
341 | char *options = NULL, *mode_opt = NULL; | ||
342 | |||
343 | info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev); | ||
344 | if (!info) { | ||
345 | dev_err(&dev->dev, "framebuffer_alloc failed\n"); | ||
346 | return -ENOMEM; | ||
347 | } | ||
348 | |||
349 | /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>] | ||
350 | * | ||
351 | * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters | ||
352 | * If address is left out, we allocate memory, | ||
353 | * if size is left out we only allocate enough to support the given mode. | ||
354 | */ | ||
355 | if (fb_get_options("grvga", &options)) { | ||
356 | retval = -ENODEV; | ||
357 | goto err; | ||
358 | } | ||
359 | |||
360 | if (!options || !*options) | ||
361 | options = "640x480-8@60"; | ||
362 | |||
363 | while (1) { | ||
364 | char *this_opt = strsep(&options, ","); | ||
365 | |||
366 | if (!this_opt) | ||
367 | break; | ||
368 | |||
369 | if (!strncmp(this_opt, "custom", 6)) { | ||
370 | if (grvga_parse_custom(this_opt, &info->var) < 0) { | ||
371 | dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt); | ||
372 | retval = -EINVAL; | ||
373 | goto err1; | ||
374 | } | ||
375 | } else if (!strncmp(this_opt, "addr", 4)) | ||
376 | grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16); | ||
377 | else if (!strncmp(this_opt, "size", 4)) | ||
378 | grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0); | ||
379 | else | ||
380 | mode_opt = this_opt; | ||
381 | } | ||
382 | |||
383 | par = info->par; | ||
384 | info->fbops = &grvga_ops; | ||
385 | info->fix = grvga_fix; | ||
386 | info->pseudo_palette = par->color_palette; | ||
387 | info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; | ||
388 | info->fix.smem_len = grvga_mem_size; | ||
389 | |||
390 | if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) { | ||
391 | dev_err(&dev->dev, "registers already mapped\n"); | ||
392 | retval = -EBUSY; | ||
393 | goto err; | ||
394 | } | ||
395 | |||
396 | par->regs = of_ioremap(&dev->resource[0], 0, | ||
397 | resource_size(&dev->resource[0]), | ||
398 | "grlib-svgactrl regs"); | ||
399 | |||
400 | if (!par->regs) { | ||
401 | dev_err(&dev->dev, "failed to map registers\n"); | ||
402 | retval = -ENOMEM; | ||
403 | goto err1; | ||
404 | } | ||
405 | |||
406 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | ||
407 | if (retval < 0) { | ||
408 | dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n"); | ||
409 | retval = -ENOMEM; | ||
410 | goto err2; | ||
411 | } | ||
412 | |||
413 | if (mode_opt) { | ||
414 | retval = fb_find_mode(&info->var, info, mode_opt, | ||
415 | grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8); | ||
416 | if (!retval || retval == 4) { | ||
417 | retval = -EINVAL; | ||
418 | goto err3; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | if (!grvga_mem_size) | ||
423 | grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8; | ||
424 | |||
425 | if (grvga_fix_addr) { | ||
426 | /* Got framebuffer base address from argument list */ | ||
427 | |||
428 | physical_start = grvga_fix_addr; | ||
429 | |||
430 | if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) { | ||
431 | dev_err(&dev->dev, "failed to request memory region\n"); | ||
432 | retval = -ENOMEM; | ||
433 | goto err3; | ||
434 | } | ||
435 | |||
436 | virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size); | ||
437 | |||
438 | if (!virtual_start) { | ||
439 | dev_err(&dev->dev, "error mapping framebuffer memory\n"); | ||
440 | retval = -ENOMEM; | ||
441 | goto err4; | ||
442 | } | ||
443 | } else { /* Allocate frambuffer memory */ | ||
444 | |||
445 | unsigned long page; | ||
446 | |||
447 | virtual_start = (unsigned long) __get_free_pages(GFP_DMA, | ||
448 | get_order(grvga_mem_size)); | ||
449 | if (!virtual_start) { | ||
450 | dev_err(&dev->dev, | ||
451 | "unable to allocate framebuffer memory (%lu bytes)\n", | ||
452 | grvga_mem_size); | ||
453 | retval = -ENOMEM; | ||
454 | goto err3; | ||
455 | } | ||
456 | |||
457 | physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE); | ||
458 | |||
459 | /* Set page reserved so that mmap will work. This is necessary | ||
460 | * since we'll be remapping normal memory. | ||
461 | */ | ||
462 | for (page = virtual_start; | ||
463 | page < PAGE_ALIGN(virtual_start + grvga_mem_size); | ||
464 | page += PAGE_SIZE) { | ||
465 | SetPageReserved(virt_to_page(page)); | ||
466 | } | ||
467 | |||
468 | par->fb_alloced = 1; | ||
469 | } | ||
470 | |||
471 | memset((unsigned long *) virtual_start, 0, grvga_mem_size); | ||
472 | |||
473 | info->screen_base = (char __iomem *) virtual_start; | ||
474 | info->fix.smem_start = physical_start; | ||
475 | info->fix.smem_len = grvga_mem_size; | ||
476 | |||
477 | dev_set_drvdata(&dev->dev, info); | ||
478 | |||
479 | dev_info(&dev->dev, | ||
480 | "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n", | ||
481 | info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel, | ||
482 | grvga_mem_size >> 10, info->screen_base); | ||
483 | |||
484 | retval = register_framebuffer(info); | ||
485 | if (retval < 0) { | ||
486 | dev_err(&dev->dev, "failed to register framebuffer\n"); | ||
487 | goto err4; | ||
488 | } | ||
489 | |||
490 | __raw_writel(physical_start, &par->regs->fb_pos); | ||
491 | __raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */ | ||
492 | &par->regs->status); | ||
493 | |||
494 | return 0; | ||
495 | |||
496 | err4: | ||
497 | dev_set_drvdata(&dev->dev, NULL); | ||
498 | if (grvga_fix_addr) { | ||
499 | release_mem_region(physical_start, grvga_mem_size); | ||
500 | iounmap((void *)virtual_start); | ||
501 | } else | ||
502 | kfree((void *)virtual_start); | ||
503 | err3: | ||
504 | fb_dealloc_cmap(&info->cmap); | ||
505 | err2: | ||
506 | of_iounmap(&dev->resource[0], par->regs, | ||
507 | resource_size(&dev->resource[0])); | ||
508 | err1: | ||
509 | release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0])); | ||
510 | err: | ||
511 | framebuffer_release(info); | ||
512 | |||
513 | return retval; | ||
514 | } | ||
515 | |||
516 | static int __devexit grvga_remove(struct platform_device *device) | ||
517 | { | ||
518 | struct fb_info *info = dev_get_drvdata(&device->dev); | ||
519 | struct grvga_par *par = info->par; | ||
520 | |||
521 | if (info) { | ||
522 | unregister_framebuffer(info); | ||
523 | fb_dealloc_cmap(&info->cmap); | ||
524 | |||
525 | of_iounmap(&device->resource[0], par->regs, | ||
526 | resource_size(&device->resource[0])); | ||
527 | release_mem_region(device->resource[0].start, resource_size(&device->resource[0])); | ||
528 | |||
529 | if (!par->fb_alloced) { | ||
530 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
531 | iounmap(info->screen_base); | ||
532 | } else | ||
533 | kfree((void *)info->screen_base); | ||
534 | |||
535 | framebuffer_release(info); | ||
536 | dev_set_drvdata(&device->dev, NULL); | ||
537 | } | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static struct of_device_id svgactrl_of_match[] = { | ||
543 | { | ||
544 | .name = "GAISLER_SVGACTRL", | ||
545 | }, | ||
546 | { | ||
547 | .name = "01_063", | ||
548 | }, | ||
549 | {}, | ||
550 | }; | ||
551 | MODULE_DEVICE_TABLE(of, svgactrl_of_match); | ||
552 | |||
553 | static struct platform_driver grvga_driver = { | ||
554 | .driver = { | ||
555 | .name = "grlib-svgactrl", | ||
556 | .owner = THIS_MODULE, | ||
557 | .of_match_table = svgactrl_of_match, | ||
558 | }, | ||
559 | .probe = grvga_probe, | ||
560 | .remove = __devexit_p(grvga_remove), | ||
561 | }; | ||
562 | |||
563 | |||
564 | static int __init grvga_init(void) | ||
565 | { | ||
566 | return platform_driver_register(&grvga_driver); | ||
567 | } | ||
568 | |||
569 | static void __exit grvga_exit(void) | ||
570 | { | ||
571 | platform_driver_unregister(&grvga_driver); | ||
572 | } | ||
573 | |||
574 | module_init(grvga_init); | ||
575 | module_exit(grvga_exit); | ||
576 | |||
577 | MODULE_LICENSE("GPL"); | ||
578 | MODULE_AUTHOR("Aeroflex Gaisler"); | ||
579 | MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver"); | ||
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index 243d16f09b8a..01fa660764b4 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c | |||
@@ -421,7 +421,8 @@ int mdp_probe(struct platform_device *pdev) | |||
421 | clk = clk_get(&pdev->dev, "mdp_clk"); | 421 | clk = clk_get(&pdev->dev, "mdp_clk"); |
422 | if (IS_ERR(clk)) { | 422 | if (IS_ERR(clk)) { |
423 | printk(KERN_INFO "mdp: failed to get mdp clk"); | 423 | printk(KERN_INFO "mdp: failed to get mdp clk"); |
424 | return PTR_ERR(clk); | 424 | ret = PTR_ERR(clk); |
425 | goto error_get_clk; | ||
425 | } | 426 | } |
426 | 427 | ||
427 | ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp); | 428 | ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp); |
@@ -495,6 +496,7 @@ int mdp_probe(struct platform_device *pdev) | |||
495 | error_device_register: | 496 | error_device_register: |
496 | free_irq(mdp->irq, mdp); | 497 | free_irq(mdp->irq, mdp); |
497 | error_request_irq: | 498 | error_request_irq: |
499 | error_get_clk: | ||
498 | iounmap(mdp->base); | 500 | iounmap(mdp->base); |
499 | error_get_irq: | 501 | error_get_irq: |
500 | error_ioremap: | 502 | error_ioremap: |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index f27ae16ead2e..66949232f85c 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, | |||
490 | 490 | ||
491 | 491 | ||
492 | /* | 492 | /* |
493 | * Parse user speficied options (`video=platinumfb:') | 493 | * Parse user specified options (`video=platinumfb:') |
494 | */ | 494 | */ |
495 | static int __init platinumfb_setup(char *options) | 495 | static int __init platinumfb_setup(char *options) |
496 | { | 496 | { |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index f4f8ce802d02..dc7bfa91e57a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table); | |||
1773 | 1773 | ||
1774 | #ifndef MODULE | 1774 | #ifndef MODULE |
1775 | /** | 1775 | /** |
1776 | * Parse user speficied options. | 1776 | * Parse user specified options. |
1777 | * | 1777 | * |
1778 | * This is, comma-separated options following `video=pm2fb:'. | 1778 | * This is, comma-separated options following `video=pm2fb:'. |
1779 | */ | 1779 | */ |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 8221b5b42da9..6632ee5ecb7e 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options) | |||
1525 | { | 1525 | { |
1526 | char *this_opt; | 1526 | char *this_opt; |
1527 | 1527 | ||
1528 | /* Parse user speficied options (`video=pm3fb:') */ | 1528 | /* Parse user specified options (`video=pm3fb:') */ |
1529 | if (!options || !*options) | 1529 | if (!options || !*options) |
1530 | return 0; | 1530 | return 0; |
1531 | 1531 | ||
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index 0283c7021090..d8de5577d3cf 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c | |||
@@ -31,8 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/version.h> | ||
35 | |||
36 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
37 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
38 | #include <linux/miscdevice.h> | 36 | #include <linux/miscdevice.h> |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 0aa13761de6e..798144a4eedd 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
767 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, | 767 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, |
768 | unsigned long val, void *data) | 768 | unsigned long val, void *data) |
769 | { | 769 | { |
770 | struct cpufreq_freqs *freqs = data; | ||
771 | struct s3c2410fb_info *info; | 770 | struct s3c2410fb_info *info; |
772 | struct fb_info *fbinfo; | 771 | struct fb_info *fbinfo; |
773 | long delta_f; | 772 | long delta_f; |
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 0f9af1aa5077..946a949f4c7d 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -1505,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = { | |||
1505 | .resume = s3_pci_resume, | 1505 | .resume = s3_pci_resume, |
1506 | }; | 1506 | }; |
1507 | 1507 | ||
1508 | /* Parse user speficied options */ | 1508 | /* Parse user specified options */ |
1509 | 1509 | ||
1510 | #ifndef MODULE | 1510 | #ifndef MODULE |
1511 | static int __init s3fb_setup(char *options) | 1511 | static int __init s3fb_setup(char *options) |
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 89158bc71da2..30f7a815a62b 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
@@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device; | |||
989 | */ | 989 | */ |
990 | int __init xxxfb_setup(char *options) | 990 | int __init xxxfb_setup(char *options) |
991 | { | 991 | { |
992 | /* Parse user speficied options (`video=xxxfb:') */ | 992 | /* Parse user specified options (`video=xxxfb:') */ |
993 | } | 993 | } |
994 | #endif /* MODULE */ | 994 | #endif /* MODULE */ |
995 | 995 | ||
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 101846c2084a..3473e75ce785 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c | |||
@@ -48,13 +48,22 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | |||
48 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; | 48 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * There are many DisplayLink-based products, all with unique PIDs. We are able | 51 | * There are many DisplayLink-based graphics products, all with unique PIDs. |
52 | * to support all volume ones (circa 2009) with a single driver, so we match | 52 | * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) |
53 | * globally on VID. TODO: Probe() needs to detect when we might be running | 53 | * We also require a match on SubClass (0x00) and Protocol (0x00), |
54 | * "future" chips, and bail on those, so a compatible driver can match. | 54 | * which is compatible with all known USB 2.0 era graphics chips and firmware, |
55 | * but allows DisplayLink to increment those for any future incompatible chips | ||
55 | */ | 56 | */ |
56 | static struct usb_device_id id_table[] = { | 57 | static struct usb_device_id id_table[] = { |
57 | {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, | 58 | {.idVendor = 0x17e9, |
59 | .bInterfaceClass = 0xff, | ||
60 | .bInterfaceSubClass = 0x00, | ||
61 | .bInterfaceProtocol = 0x00, | ||
62 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | ||
63 | USB_DEVICE_ID_MATCH_INT_CLASS | | ||
64 | USB_DEVICE_ID_MATCH_INT_SUBCLASS | | ||
65 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, | ||
66 | }, | ||
58 | {}, | 67 | {}, |
59 | }; | 68 | }; |
60 | MODULE_DEVICE_TABLE(usb, id_table); | 69 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -1613,7 +1622,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
1613 | /* We don't register a new USB class. Our client interface is fbdev */ | 1622 | /* We don't register a new USB class. Our client interface is fbdev */ |
1614 | 1623 | ||
1615 | /* allocates framebuffer driver structure, not framebuffer memory */ | 1624 | /* allocates framebuffer driver structure, not framebuffer memory */ |
1616 | info = framebuffer_alloc(0, &usbdev->dev); | 1625 | info = framebuffer_alloc(0, &interface->dev); |
1617 | if (!info) { | 1626 | if (!info) { |
1618 | retval = -ENOMEM; | 1627 | retval = -ENOMEM; |
1619 | pr_err("framebuffer_alloc failed\n"); | 1628 | pr_err("framebuffer_alloc failed\n"); |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 6b52bf65f0b5..3f5a041601da 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info, | |||
555 | 555 | ||
556 | 556 | ||
557 | /* | 557 | /* |
558 | * Parse user speficied options (`video=valkyriefb:') | 558 | * Parse user specified options (`video=valkyriefb:') |
559 | */ | 559 | */ |
560 | int __init valkyriefb_setup(char *options) | 560 | int __init valkyriefb_setup(char *options) |
561 | { | 561 | { |
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h index ae35cfdeb37c..013884543e91 100644 --- a/drivers/video/via/via_modesetting.h +++ b/drivers/video/via/via_modesetting.h | |||
@@ -28,6 +28,11 @@ | |||
28 | 28 | ||
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | 30 | ||
31 | |||
32 | #define VIA_PITCH_SIZE (1<<3) | ||
33 | #define VIA_PITCH_MAX 0x3FF8 | ||
34 | |||
35 | |||
31 | void via_set_primary_address(u32 addr); | 36 | void via_set_primary_address(u32 addr); |
32 | void via_set_secondary_address(u32 addr); | 37 | void via_set_secondary_address(u32 addr); |
33 | void via_set_primary_pitch(u32 pitch); | 38 | void via_set_primary_pitch(u32 pitch); |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 53aa4430d86e..09fa57cea844 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -151,7 +151,8 @@ static void viafb_update_fix(struct fb_info *info) | |||
151 | 151 | ||
152 | info->fix.visual = | 152 | info->fix.visual = |
153 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 153 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
154 | info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; | 154 | info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, |
155 | VIA_PITCH_SIZE); | ||
155 | } | 156 | } |
156 | 157 | ||
157 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, | 158 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, |
@@ -238,8 +239,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
238 | depth = 24; | 239 | depth = 24; |
239 | 240 | ||
240 | viafb_fill_var_color_info(var, depth); | 241 | viafb_fill_var_color_info(var, depth); |
241 | line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; | 242 | if (var->xres_virtual < var->xres) |
242 | if (line * var->yres_virtual > ppar->memsize) | 243 | var->xres_virtual = var->xres; |
244 | |||
245 | line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, | ||
246 | VIA_PITCH_SIZE); | ||
247 | if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) | ||
243 | return -EINVAL; | 248 | return -EINVAL; |
244 | 249 | ||
245 | /* Based on var passed in to calculate the refresh, | 250 | /* Based on var passed in to calculate the refresh, |
@@ -348,8 +353,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, | |||
348 | struct fb_info *info) | 353 | struct fb_info *info) |
349 | { | 354 | { |
350 | struct viafb_par *viapar = info->par; | 355 | struct viafb_par *viapar = info->par; |
351 | u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) | 356 | u32 vram_addr = viapar->vram_addr |
352 | * (var->bits_per_pixel / 8) + viapar->vram_addr; | 357 | + var->yoffset * info->fix.line_length |
358 | + var->xoffset * info->var.bits_per_pixel / 8; | ||
353 | 359 | ||
354 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); | 360 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); |
355 | if (!viafb_dual_fb) { | 361 | if (!viafb_dual_fb) { |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 77dea015ff69..fcb6cd90f64d 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/version.h> | ||
27 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
28 | #include <linux/string.h> | 27 | #include <linux/string.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |