aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
commit7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch)
treee730a4565e0318140d2fbd2f0415d18a339d7336 /drivers/video
parent41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff)
parent0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff)
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig191
-rw-r--r--drivers/video/Makefile8
-rw-r--r--drivers/video/acornfb.c5
-rw-r--r--drivers/video/am200epd.c295
-rw-r--r--drivers/video/amifb.c27
-rw-r--r--drivers/video/arkfb.c28
-rw-r--r--drivers/video/atafb.c12
-rw-r--r--drivers/video/atmel_lcdfb.c176
-rw-r--r--drivers/video/aty/aty128fb.c8
-rw-r--r--drivers/video/aty/atyfb_base.c129
-rw-r--r--drivers/video/aty/radeon_accel.c313
-rw-r--r--drivers/video/aty/radeon_backlight.c2
-rw-r--r--drivers/video/aty/radeon_base.c55
-rw-r--r--drivers/video/aty/radeon_i2c.c7
-rw-r--r--drivers/video/aty/radeon_pm.c6
-rw-r--r--drivers/video/aty/radeonfb.h55
-rw-r--r--drivers/video/backlight/Kconfig97
-rw-r--r--drivers/video/backlight/Makefile14
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c244
-rw-r--r--drivers/video/backlight/backlight.c1
-rw-r--r--drivers/video/backlight/corgi_lcd.c641
-rw-r--r--drivers/video/backlight/da903x.c201
-rw-r--r--drivers/video/backlight/hp680_bl.c4
-rw-r--r--drivers/video/backlight/ili9320.c330
-rw-r--r--drivers/video/backlight/ili9320.h80
-rw-r--r--drivers/video/backlight/kb3886_bl.c204
-rw-r--r--drivers/video/backlight/lcd.c18
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c114
-rw-r--r--drivers/video/backlight/omap1_bl.c6
-rw-r--r--drivers/video/backlight/platform_lcd.c174
-rw-r--r--drivers/video/backlight/pwm_bl.c10
-rw-r--r--drivers/video/backlight/tdo24m.c396
-rw-r--r--drivers/video/backlight/tosa_bl.c198
-rw-r--r--drivers/video/backlight/tosa_lcd.c280
-rw-r--r--drivers/video/backlight/vgg2432a4.c284
-rw-r--r--drivers/video/bf54x-lq043fb.c19
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c2
-rw-r--r--drivers/video/bw2.c2
-rw-r--r--drivers/video/c2p.c3
-rw-r--r--drivers/video/carminefb.c790
-rw-r--r--drivers/video/carminefb.h64
-rw-r--r--drivers/video/carminefb_regs.h159
-rw-r--r--drivers/video/cg14.c2
-rw-r--r--drivers/video/cg3.c2
-rw-r--r--drivers/video/cg6.c38
-rw-r--r--drivers/video/cirrusfb.c636
-rw-r--r--drivers/video/clps711xfb.c4
-rw-r--r--drivers/video/cobalt_lcdfb.c371
-rw-r--r--drivers/video/console/.gitignore2
-rw-r--r--drivers/video/console/Kconfig16
-rw-r--r--drivers/video/console/fbcon.c60
-rw-r--r--drivers/video/console/fbcon.h8
-rw-r--r--drivers/video/console/mdacon.c6
-rw-r--r--drivers/video/console/sticon.c6
-rw-r--r--drivers/video/console/sticore.c63
-rw-r--r--drivers/video/console/vgacon.c43
-rw-r--r--drivers/video/cyber2000fb.c2
-rw-r--r--drivers/video/display/display-sysfs.c9
-rw-r--r--drivers/video/efifb.c191
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/fb_defio.c19
-rw-r--r--drivers/video/fbmem.c205
-rw-r--r--drivers/video/fbmon.c10
-rw-r--r--drivers/video/ffb.c2
-rw-r--r--drivers/video/fsl-diu-fb.c100
-rw-r--r--drivers/video/gbefb.c50
-rw-r--r--drivers/video/geode/lxfb.h2
-rw-r--r--drivers/video/geode/lxfb_ops.c28
-rw-r--r--drivers/video/hgafb.c36
-rw-r--r--drivers/video/hitfb.c2
-rw-r--r--drivers/video/imacfb.c376
-rw-r--r--drivers/video/imxfb.c5
-rw-r--r--drivers/video/intelfb/intelfb.h7
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c7
-rw-r--r--drivers/video/intelfb/intelfbhw.c7
-rw-r--r--drivers/video/leo.c96
-rw-r--r--drivers/video/macfb.c2
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c21
-rw-r--r--drivers/video/matrox/matroxfb_base.c11
-rw-r--r--drivers/video/matrox/matroxfb_maven.c97
-rw-r--r--drivers/video/metronomefb.c288
-rw-r--r--drivers/video/neofb.c275
-rw-r--r--drivers/video/offb.c192
-rw-r--r--drivers/video/omap/blizzard.c6
-rw-r--r--drivers/video/omap/dispc.c28
-rw-r--r--drivers/video/omap/dispc.h2
-rw-r--r--drivers/video/omap/hwa742.c6
-rw-r--r--drivers/video/omap/lcd_h3.c4
-rw-r--r--drivers/video/omap/lcd_h4.c6
-rw-r--r--drivers/video/omap/lcd_inn1510.c4
-rw-r--r--drivers/video/omap/lcd_inn1610.c26
-rw-r--r--drivers/video/omap/lcd_osk.c16
-rw-r--r--drivers/video/omap/lcd_palmte.c4
-rw-r--r--drivers/video/omap/lcd_palmtt.c4
-rw-r--r--drivers/video/omap/lcd_palmz71.c2
-rw-r--r--drivers/video/omap/lcd_sx1.c107
-rw-r--r--drivers/video/omap/lcdc.c6
-rw-r--r--drivers/video/omap/lcdc.h2
-rw-r--r--drivers/video/omap/omapfb_main.c21
-rw-r--r--drivers/video/omap/rfbi.c11
-rw-r--r--drivers/video/omap/sossi.c14
-rw-r--r--drivers/video/p9100.c2
-rw-r--r--drivers/video/pm2fb.c1
-rw-r--r--drivers/video/pnx4008/dum.h2
-rw-r--r--drivers/video/pnx4008/sdum.c2
-rw-r--r--drivers/video/ps3fb.c1
-rw-r--r--drivers/video/pvr2fb.c6
-rw-r--r--drivers/video/pxafb.c152
-rw-r--r--drivers/video/pxafb.h2
-rw-r--r--drivers/video/s1d13xxxfb.c23
-rw-r--r--drivers/video/s3c2410fb.c6
-rw-r--r--drivers/video/s3fb.c19
-rw-r--r--drivers/video/sa1100fb.c14
-rw-r--r--drivers/video/sa1100fb.h2
-rw-r--r--drivers/video/sh7760fb.c659
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c737
-rw-r--r--drivers/video/sis/init.h1
-rw-r--r--drivers/video/sis/init301.h1
-rw-r--r--drivers/video/sis/initextlfb.c1
-rw-r--r--drivers/video/sis/osdef.h1
-rw-r--r--drivers/video/sis/sis.h22
-rw-r--r--drivers/video/sis/sis_accel.c1
-rw-r--r--drivers/video/sis/sis_main.c44
-rw-r--r--drivers/video/sis/sis_main.h4
-rw-r--r--drivers/video/sis/vgatypes.h4
-rw-r--r--drivers/video/skeletonfb.c37
-rw-r--r--drivers/video/sm501fb.c329
-rw-r--r--drivers/video/sticore.h2
-rw-r--r--drivers/video/stifb.c6
-rw-r--r--drivers/video/tcx.c2
-rw-r--r--drivers/video/tdfxfb.c59
-rw-r--r--drivers/video/tmiofb.c1050
-rw-r--r--drivers/video/tridentfb.c1350
-rw-r--r--drivers/video/uvesafb.c15
-rw-r--r--drivers/video/vermilion/vermilion.h1
-rw-r--r--drivers/video/vfb.c14
-rw-r--r--drivers/video/vga16fb.c133
-rw-r--r--drivers/video/via/Makefile7
-rw-r--r--drivers/video/via/accel.c279
-rw-r--r--drivers/video/via/accel.h169
-rw-r--r--drivers/video/via/chip.h190
-rw-r--r--drivers/video/via/debug.h41
-rw-r--r--drivers/video/via/dvi.c682
-rw-r--r--drivers/video/via/dvi.h64
-rw-r--r--drivers/video/via/global.c60
-rw-r--r--drivers/video/via/global.h90
-rw-r--r--drivers/video/via/hw.c2865
-rw-r--r--drivers/video/via/hw.h933
-rw-r--r--drivers/video/via/iface.c78
-rw-r--r--drivers/video/via/iface.h38
-rw-r--r--drivers/video/via/ioctl.c112
-rw-r--r--drivers/video/via/ioctl.h210
-rw-r--r--drivers/video/via/lcd.c1821
-rw-r--r--drivers/video/via/lcd.h94
-rw-r--r--drivers/video/via/lcdtbl.h591
-rw-r--r--drivers/video/via/share.h1105
-rw-r--r--drivers/video/via/tbl1636.c71
-rw-r--r--drivers/video/via/tbl1636.h34
-rw-r--r--drivers/video/via/tblDPASetting.c109
-rw-r--r--drivers/video/via/tblDPASetting.h47
-rw-r--r--drivers/video/via/via_i2c.c177
-rw-r--r--drivers/video/via/via_i2c.h46
-rw-r--r--drivers/video/via/via_utility.c253
-rw-r--r--drivers/video/via/via_utility.h35
-rw-r--r--drivers/video/via/viafbdev.c2571
-rw-r--r--drivers/video/via/viafbdev.h112
-rw-r--r--drivers/video/via/viamode.c1086
-rw-r--r--drivers/video/via/viamode.h177
-rw-r--r--drivers/video/via/vt1636.c306
-rw-r--r--drivers/video/via/vt1636.h44
-rw-r--r--drivers/video/vt8623fb.c30
-rw-r--r--drivers/video/xen-fbfront.c4
-rw-r--r--drivers/video/xilinxfb.c1
174 files changed, 25135 insertions, 3323 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9b887ef64ff1..0f13448c6f79 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -76,6 +76,14 @@ config FB_DDC
76 select I2C 76 select I2C
77 default n 77 default n
78 78
79config FB_BOOT_VESA_SUPPORT
80 bool
81 depends on FB
82 default n
83 ---help---
84 If true, at least one selected framebuffer driver can take advantage
85 of VESA video modes set at an early boot stage via the vga= parameter.
86
79config FB_CFB_FILLRECT 87config FB_CFB_FILLRECT
80 tristate 88 tristate
81 depends on FB 89 depends on FB
@@ -172,11 +180,6 @@ config FB_DEFERRED_IO
172 bool 180 bool
173 depends on FB 181 depends on FB
174 182
175config FB_METRONOME
176 tristate
177 depends on FB
178 depends on FB_DEFERRED_IO
179
180config FB_HECUBA 183config FB_HECUBA
181 tristate 184 tristate
182 depends on FB 185 depends on FB
@@ -259,16 +262,24 @@ config FB_PM2
259 select FB_CFB_COPYAREA 262 select FB_CFB_COPYAREA
260 select FB_CFB_IMAGEBLIT 263 select FB_CFB_IMAGEBLIT
261 help 264 help
262 This is the frame buffer device driver for the Permedia2 AGP frame 265 This is the frame buffer device driver for cards based on
263 buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a 266 the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
264 product page at 267 The driver was tested on the following cards:
265 <http://www.ask.com.hk/product/Permedia%202/permedia2.htm>. 268 Diamond FireGL 1000 PRO AGP
269 ELSA Gloria Synergy PCI
270 Appian Jeronimo PRO (both heads) PCI
271 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
272 Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
273 ASK Graphic Blaster Exxtreme AGP
274
275 To compile this driver as a module, choose M here: the
276 module will be called pm2fb.
266 277
267config FB_PM2_FIFO_DISCONNECT 278config FB_PM2_FIFO_DISCONNECT
268 bool "enable FIFO disconnect feature" 279 bool "enable FIFO disconnect feature"
269 depends on FB_PM2 && PCI 280 depends on FB_PM2 && PCI
270 help 281 help
271 Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2). 282 Support the Permedia2 FIFO disconnect feature.
272 283
273config FB_ARMCLCD 284config FB_ARMCLCD
274 tristate "ARM PrimeCell PL110 support" 285 tristate "ARM PrimeCell PL110 support"
@@ -678,7 +689,7 @@ config FB_VESA
678 select FB_CFB_FILLRECT 689 select FB_CFB_FILLRECT
679 select FB_CFB_COPYAREA 690 select FB_CFB_COPYAREA
680 select FB_CFB_IMAGEBLIT 691 select FB_CFB_IMAGEBLIT
681 select VIDEO_SELECT 692 select FB_BOOT_VESA_SUPPORT
682 help 693 help
683 This is the frame buffer device driver for generic VESA 2.0 694 This is the frame buffer device driver for generic VESA 2.0
684 compliant graphic cards. The older VESA 1.2 cards are not supported. 695 compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -687,23 +698,14 @@ config FB_VESA
687 698
688config FB_EFI 699config FB_EFI
689 bool "EFI-based Framebuffer Support" 700 bool "EFI-based Framebuffer Support"
690 depends on (FB = y) && X86
691 select FB_CFB_FILLRECT
692 select FB_CFB_COPYAREA
693 select FB_CFB_IMAGEBLIT
694 help
695 This is the EFI frame buffer device driver. If the firmware on
696 your platform is UEFI2.0, select Y to add support for
697 Graphics Output Protocol for early console messages to appear.
698
699config FB_IMAC
700 bool "Intel-based Macintosh Framebuffer Support"
701 depends on (FB = y) && X86 && EFI 701 depends on (FB = y) && X86 && EFI
702 select FB_CFB_FILLRECT 702 select FB_CFB_FILLRECT
703 select FB_CFB_COPYAREA 703 select FB_CFB_COPYAREA
704 select FB_CFB_IMAGEBLIT 704 select FB_CFB_IMAGEBLIT
705 help 705 help
706 This is the frame buffer device driver for the Intel-based Macintosh 706 This is the EFI frame buffer device driver. If the firmware on
707 your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
708 using the EFI framebuffer as your console.
707 709
708config FB_N411 710config FB_N411
709 tristate "N411 Apollo/Hecuba devkit support" 711 tristate "N411 Apollo/Hecuba devkit support"
@@ -1124,6 +1126,7 @@ config FB_INTEL
1124 select FB_CFB_FILLRECT 1126 select FB_CFB_FILLRECT
1125 select FB_CFB_COPYAREA 1127 select FB_CFB_COPYAREA
1126 select FB_CFB_IMAGEBLIT 1128 select FB_CFB_IMAGEBLIT
1129 select FB_BOOT_VESA_SUPPORT
1127 help 1130 help
1128 This driver supports the on-board graphics built in to the Intel 1131 This driver supports the on-board graphics built in to the Intel
1129 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. 1132 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
@@ -1476,6 +1479,7 @@ config FB_SIS
1476 select FB_CFB_FILLRECT 1479 select FB_CFB_FILLRECT
1477 select FB_CFB_COPYAREA 1480 select FB_CFB_COPYAREA
1478 select FB_CFB_IMAGEBLIT 1481 select FB_CFB_IMAGEBLIT
1482 select FB_BOOT_VESA_SUPPORT
1479 help 1483 help
1480 This is the frame buffer device driver for the SiS 300, 315, 330 1484 This is the frame buffer device driver for the SiS 300, 315, 330
1481 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. 1485 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
@@ -1498,6 +1502,24 @@ config FB_SIS_315
1498 (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well 1502 (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
1499 as XGI V3XT, V5, V8 and Z7. 1503 as XGI V3XT, V5, V8 and Z7.
1500 1504
1505config FB_VIA
1506 tristate "VIA UniChrome (Pro) and Chrome9 display support"
1507 depends on FB && PCI
1508 select FB_CFB_FILLRECT
1509 select FB_CFB_COPYAREA
1510 select FB_CFB_IMAGEBLIT
1511 select FB_SOFT_CURSOR
1512 select I2C_ALGOBIT
1513 select I2C
1514 help
1515 This is the frame buffer device driver for Graphics chips of VIA
1516 UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
1517 CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
1518 /P4M900,VX800)
1519 Say Y if you have a VIA UniChrome graphics board.
1520
1521 To compile this driver as a module, choose M here: the
1522 module will be called viafb.
1501config FB_NEOMAGIC 1523config FB_NEOMAGIC
1502 tristate "NeoMagic display support" 1524 tristate "NeoMagic display support"
1503 depends on FB && PCI 1525 depends on FB && PCI
@@ -1527,25 +1549,25 @@ config FB_KYRO
1527 module will be called kyrofb. 1549 module will be called kyrofb.
1528 1550
1529config FB_3DFX 1551config FB_3DFX
1530 tristate "3Dfx Banshee/Voodoo3 display support" 1552 tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
1531 depends on FB && PCI 1553 depends on FB && PCI
1532 select FB_CFB_IMAGEBLIT 1554 select FB_CFB_IMAGEBLIT
1533 select FB_CFB_FILLRECT 1555 select FB_CFB_FILLRECT
1534 select FB_CFB_COPYAREA 1556 select FB_CFB_COPYAREA
1535 help 1557 help
1536 This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 1558 This driver supports graphics boards with the 3Dfx Banshee,
1537 chips. Say Y if you have such a graphics board. 1559 Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
1560 such a graphics board.
1538 1561
1539 To compile this driver as a module, choose M here: the 1562 To compile this driver as a module, choose M here: the
1540 module will be called tdfxfb. 1563 module will be called tdfxfb.
1541 1564
1542config FB_3DFX_ACCEL 1565config FB_3DFX_ACCEL
1543 bool "3Dfx Banshee/Voodoo3 Acceleration functions (EXPERIMENTAL)" 1566 bool "3Dfx Acceleration functions (EXPERIMENTAL)"
1544 depends on FB_3DFX && EXPERIMENTAL 1567 depends on FB_3DFX && EXPERIMENTAL
1545 ---help--- 1568 ---help---
1546 This will compile the 3Dfx Banshee/Voodoo3 frame buffer device 1569 This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
1547 with acceleration functions. 1570 device driver with acceleration functions.
1548
1549 1571
1550config FB_VOODOO1 1572config FB_VOODOO1
1551 tristate "3Dfx Voodoo Graphics (sst1) support" 1573 tristate "3Dfx Voodoo Graphics (sst1) support"
@@ -1583,7 +1605,6 @@ config FB_CYBLA
1583 tristate "Cyberblade/i1 support" 1605 tristate "Cyberblade/i1 support"
1584 depends on FB && PCI && X86_32 && !64BIT 1606 depends on FB && PCI && X86_32 && !64BIT
1585 select FB_CFB_IMAGEBLIT 1607 select FB_CFB_IMAGEBLIT
1586 select VIDEO_SELECT
1587 ---help--- 1608 ---help---
1588 This driver is supposed to support the Trident Cyberblade/i1 1609 This driver is supposed to support the Trident Cyberblade/i1
1589 graphics core integrated in the VIA VT8601A North Bridge, 1610 graphics core integrated in the VIA VT8601A North Bridge,
@@ -1611,17 +1632,16 @@ config FB_TRIDENT
1611 select FB_CFB_COPYAREA 1632 select FB_CFB_COPYAREA
1612 select FB_CFB_IMAGEBLIT 1633 select FB_CFB_IMAGEBLIT
1613 ---help--- 1634 ---help---
1614 This driver is supposed to support graphics boards with the 1635 This is the frame buffer device driver for Trident PCI/AGP chipsets.
1615 Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops 1636 Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
1637 and Blade XP.
1638 There are also integrated versions of these chips called CyberXXXX,
1639 CyberImage or CyberBlade. These chips are mostly found in laptops
1616 but also on some motherboards. For more information, read 1640 but also on some motherboards. For more information, read
1617 <file:Documentation/fb/tridentfb.txt> 1641 <file:Documentation/fb/tridentfb.txt>
1618 1642
1619 Cyberblade/i1 support will be removed soon, use the cyblafb driver
1620 instead.
1621
1622 Say Y if you have such a graphics board. 1643 Say Y if you have such a graphics board.
1623 1644
1624
1625 To compile this driver as a module, choose M here: the 1645 To compile this driver as a module, choose M here: the
1626 module will be called tridentfb. 1646 module will be called tridentfb.
1627 1647
@@ -1658,6 +1678,32 @@ config FB_PM3
1658 similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 1678 similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
1659 and maybe other boards. 1679 and maybe other boards.
1660 1680
1681config FB_CARMINE
1682 tristate "Fujitsu carmine frame buffer support"
1683 depends on FB && PCI
1684 select FB_CFB_FILLRECT
1685 select FB_CFB_COPYAREA
1686 select FB_CFB_IMAGEBLIT
1687 help
1688 This is the frame buffer device driver for the Fujitsu Carmine chip.
1689 The driver provides two independent frame buffer devices.
1690
1691choice
1692 depends on FB_CARMINE
1693 prompt "DRAM timing"
1694 default FB_CARMINE_DRAM_EVAL
1695
1696config FB_CARMINE_DRAM_EVAL
1697 bool "Eval board timings"
1698 help
1699 Use timings which work on the eval card.
1700
1701config CARMINE_DRAM_CUSTOM
1702 bool "Custom board timings"
1703 help
1704 Use custom board timings.
1705endchoice
1706
1661config FB_AU1100 1707config FB_AU1100
1662 bool "Au1100 LCD Driver" 1708 bool "Au1100 LCD Driver"
1663 depends on (FB = y) && MIPS && SOC_AU1100 1709 depends on (FB = y) && MIPS && SOC_AU1100
@@ -1840,6 +1886,38 @@ config FB_W100
1840 1886
1841 If unsure, say N. 1887 If unsure, say N.
1842 1888
1889config FB_SH_MOBILE_LCDC
1890 tristate "SuperH Mobile LCDC framebuffer support"
1891 depends on FB && SUPERH
1892 select FB_CFB_FILLRECT
1893 select FB_CFB_COPYAREA
1894 select FB_CFB_IMAGEBLIT
1895 default m
1896 ---help---
1897 Frame buffer driver for the on-chip SH-Mobile LCD controller.
1898
1899config FB_TMIO
1900 tristate "Toshiba Mobile IO FrameBuffer support"
1901 depends on FB && MFD_CORE
1902 select FB_CFB_FILLRECT
1903 select FB_CFB_COPYAREA
1904 select FB_CFB_IMAGEBLIT
1905 ---help---
1906 Frame buffer driver for the Toshiba Mobile IO integrated as found
1907 on the Sharp SL-6000 series
1908
1909 This driver is also available as a module ( = code which can be
1910 inserted and removed from the running kernel whenever you want). The
1911 module will be called tmiofb. If you want to compile it as a module,
1912 say M here and read <file:Documentation/kbuild/modules.txt>.
1913
1914 If unsure, say N.
1915
1916config FB_TMIO_ACCELL
1917 bool "tmiofb acceleration"
1918 depends on FB_TMIO
1919 default y
1920
1843config FB_S3C2410 1921config FB_S3C2410
1844 tristate "S3C2410 LCD framebuffer support" 1922 tristate "S3C2410 LCD framebuffer support"
1845 depends on FB && ARCH_S3C2410 1923 depends on FB && ARCH_S3C2410
@@ -1938,18 +2016,22 @@ config FB_XILINX
1938 framebuffer. ML300 carries a 640*480 LCD display on the board, 2016 framebuffer. ML300 carries a 640*480 LCD display on the board,
1939 ML403 uses a standard DB15 VGA connector. 2017 ML403 uses a standard DB15 VGA connector.
1940 2018
1941config FB_AM200EPD 2019config FB_COBALT
1942 tristate "AM-200 E-Ink EPD devkit support" 2020 tristate "Cobalt server LCD frame buffer support"
1943 depends on FB && ARCH_PXA && MMU 2021 depends on FB && MIPS_COBALT
1944 select FB_SYS_FILLRECT 2022
1945 select FB_SYS_COPYAREA 2023config FB_SH7760
1946 select FB_SYS_IMAGEBLIT 2024 bool "SH7760/SH7763 LCDC support"
1947 select FB_SYS_FOPS 2025 depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763)
1948 select FB_DEFERRED_IO 2026 select FB_CFB_FILLRECT
1949 select FB_METRONOME 2027 select FB_CFB_COPYAREA
2028 select FB_CFB_IMAGEBLIT
1950 help 2029 help
1951 This enables support for the Metronome display controller used on 2030 Support for the SH7760/SH7763 integrated (D)STN/TFT LCD Controller.
1952 the E-Ink AM-200 EPD devkit. 2031 Supports display resolutions up to 1024x1024 pixel, grayscale and
2032 color operation, with depths ranging from 1 bpp to 8 bpp monochrome
2033 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for
2034 panels <= 320 pixel horizontal resolution.
1953 2035
1954config FB_VIRTUAL 2036config FB_VIRTUAL
1955 tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" 2037 tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
@@ -1988,6 +2070,19 @@ config XEN_FBDEV_FRONTEND
1988 frame buffer driver. It communicates with a back-end 2070 frame buffer driver. It communicates with a back-end
1989 in another domain. 2071 in another domain.
1990 2072
2073config FB_METRONOME
2074 tristate "E-Ink Metronome/8track controller support"
2075 depends on FB
2076 select FB_SYS_FILLRECT
2077 select FB_SYS_COPYAREA
2078 select FB_SYS_IMAGEBLIT
2079 select FB_SYS_FOPS
2080 select FB_DEFERRED_IO
2081 help
2082 This driver implements support for the E-Ink Metronome
2083 controller. The pre-release name for this device was 8track
2084 and could also have been called by some vendors as PVI-nnnn.
2085
1991source "drivers/video/omap/Kconfig" 2086source "drivers/video/omap/Kconfig"
1992 2087
1993source "drivers/video/backlight/Kconfig" 2088source "drivers/video/backlight/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 04bca35403ff..248bddc8d0b0 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
29 29
30# Hardware specific drivers go first 30# Hardware specific drivers go first
31obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o 31obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
32obj-$(CONFIG_FB_AM200EPD) += am200epd.o
33obj-$(CONFIG_FB_ARC) += arcfb.o 32obj-$(CONFIG_FB_ARC) += arcfb.o
34obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o 33obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
35obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o 34obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
@@ -43,6 +42,7 @@ obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
43obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o 42obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
44obj-$(CONFIG_FB_RADEON) += aty/ 43obj-$(CONFIG_FB_RADEON) += aty/
45obj-$(CONFIG_FB_SIS) += sis/ 44obj-$(CONFIG_FB_SIS) += sis/
45obj-$(CONFIG_FB_VIA) += via/
46obj-$(CONFIG_FB_KYRO) += kyro/ 46obj-$(CONFIG_FB_KYRO) += kyro/
47obj-$(CONFIG_FB_SAVAGE) += savage/ 47obj-$(CONFIG_FB_SAVAGE) += savage/
48obj-$(CONFIG_FB_GEODE) += geode/ 48obj-$(CONFIG_FB_GEODE) += geode/
@@ -98,6 +98,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
98obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o 98obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
99obj-$(CONFIG_FB_PXA) += pxafb.o 99obj-$(CONFIG_FB_PXA) += pxafb.o
100obj-$(CONFIG_FB_W100) += w100fb.o 100obj-$(CONFIG_FB_W100) += w100fb.o
101obj-$(CONFIG_FB_TMIO) += tmiofb.o
101obj-$(CONFIG_FB_AU1100) += au1100fb.o 102obj-$(CONFIG_FB_AU1100) += au1100fb.o
102obj-$(CONFIG_FB_AU1200) += au1200fb.o 103obj-$(CONFIG_FB_AU1200) += au1200fb.o
103obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o 104obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
@@ -106,22 +107,25 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
106obj-$(CONFIG_FB_MAXINE) += maxinefb.o 107obj-$(CONFIG_FB_MAXINE) += maxinefb.o
107obj-$(CONFIG_FB_METRONOME) += metronomefb.o 108obj-$(CONFIG_FB_METRONOME) += metronomefb.o
108obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o 109obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
110obj-$(CONFIG_FB_SH7760) += sh7760fb.o
109obj-$(CONFIG_FB_IMX) += imxfb.o 111obj-$(CONFIG_FB_IMX) += imxfb.o
110obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o 112obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
111obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o 113obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
114obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
112obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ 115obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
113obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ 116obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
114obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o 117obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
115obj-$(CONFIG_FB_PS3) += ps3fb.o 118obj-$(CONFIG_FB_PS3) += ps3fb.o
116obj-$(CONFIG_FB_SM501) += sm501fb.o 119obj-$(CONFIG_FB_SM501) += sm501fb.o
117obj-$(CONFIG_FB_XILINX) += xilinxfb.o 120obj-$(CONFIG_FB_XILINX) += xilinxfb.o
121obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
118obj-$(CONFIG_FB_OMAP) += omap/ 122obj-$(CONFIG_FB_OMAP) += omap/
119obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o 123obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
124obj-$(CONFIG_FB_CARMINE) += carminefb.o
120 125
121# Platform or fallback drivers go here 126# Platform or fallback drivers go here
122obj-$(CONFIG_FB_UVESA) += uvesafb.o 127obj-$(CONFIG_FB_UVESA) += uvesafb.o
123obj-$(CONFIG_FB_VESA) += vesafb.o 128obj-$(CONFIG_FB_VESA) += vesafb.o
124obj-$(CONFIG_FB_IMAC) += imacfb.o
125obj-$(CONFIG_FB_EFI) += efifb.o 129obj-$(CONFIG_FB_EFI) += efifb.o
126obj-$(CONFIG_FB_VGA16) += vga16fb.o 130obj-$(CONFIG_FB_VGA16) += vga16fb.o
127obj-$(CONFIG_FB_OF) += offb.o 131obj-$(CONFIG_FB_OF) += offb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index eedb8285e32f..61c3d3f40fd1 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -23,12 +23,13 @@
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/ctype.h> 24#include <linux/ctype.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/mm.h>
26#include <linux/init.h> 27#include <linux/init.h>
27#include <linux/fb.h> 28#include <linux/fb.h>
28#include <linux/platform_device.h> 29#include <linux/platform_device.h>
29#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
30 31
31#include <asm/hardware.h> 32#include <mach/hardware.h>
32#include <asm/io.h> 33#include <asm/io.h>
33#include <asm/irq.h> 34#include <asm/irq.h>
34#include <asm/mach-types.h> 35#include <asm/mach-types.h>
@@ -338,7 +339,7 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
338#endif 339#endif
339 340
340#ifdef HAS_VIDC20 341#ifdef HAS_VIDC20
341#include <asm/arch/acornfb.h> 342#include <mach/acornfb.h>
342 343
343#define MAX_SIZE 2*1024*1024 344#define MAX_SIZE 2*1024*1024
344 345
diff --git a/drivers/video/am200epd.c b/drivers/video/am200epd.c
deleted file mode 100644
index 51e26c1f5e8b..000000000000
--- a/drivers/video/am200epd.c
+++ /dev/null
@@ -1,295 +0,0 @@
1/*
2 * linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
3 *
4 * Copyright (C) 2008, Jaya Kumar
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 *
10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
11 *
12 * This work was made possible by help and equipment support from E-Ink
13 * Corporation. http://support.eink.com/community
14 *
15 * This driver is written to be used with the Metronome display controller.
16 * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
17 * Vizplex EPD on a Gumstix board using the Lyre interface board.
18 *
19 */
20
21#include <linux/module.h>
22#include <linux/kernel.h>
23#include <linux/errno.h>
24#include <linux/string.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/fb.h>
28#include <linux/init.h>
29#include <linux/platform_device.h>
30#include <linux/list.h>
31#include <linux/uaccess.h>
32#include <linux/irq.h>
33
34#include <video/metronomefb.h>
35
36#include <asm/arch/pxa-regs.h>
37
38/* register offsets for gpio control */
39#define LED_GPIO_PIN 51
40#define STDBY_GPIO_PIN 48
41#define RST_GPIO_PIN 49
42#define RDY_GPIO_PIN 32
43#define ERR_GPIO_PIN 17
44#define PCBPWR_GPIO_PIN 16
45
46#define AF_SEL_GPIO_N 0x3
47#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
48#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
49#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
50#define GPDR1_OFFSET(pin) (pin - 32)
51#define GPCR1_OFFSET(pin) (pin - 32)
52#define GPSR1_OFFSET(pin) (pin - 32)
53#define GPCR0_OFFSET(pin) (pin)
54#define GPSR0_OFFSET(pin) (pin)
55
56static void am200_set_gpio_output(int pin, int val)
57{
58 u8 index;
59
60 index = pin >> 4;
61
62 switch (index) {
63 case 1:
64 if (val)
65 GPSR0 |= (1 << GPSR0_OFFSET(pin));
66 else
67 GPCR0 |= (1 << GPCR0_OFFSET(pin));
68 break;
69 case 2:
70 break;
71 case 3:
72 if (val)
73 GPSR1 |= (1 << GPSR1_OFFSET(pin));
74 else
75 GPCR1 |= (1 << GPCR1_OFFSET(pin));
76 break;
77 default:
78 printk(KERN_ERR "unimplemented\n");
79 }
80}
81
82static void __devinit am200_init_gpio_pin(int pin, int dir)
83{
84 u8 index;
85 /* dir 0 is output, 1 is input
86 - do 2 things here:
87 - set gpio alternate function to standard gpio
88 - set gpio direction to input or output */
89
90 index = pin >> 4;
91 switch (index) {
92 case 1:
93 GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
94
95 if (dir)
96 GPDR0 &= ~(1 << pin);
97 else
98 GPDR0 |= (1 << pin);
99 break;
100 case 2:
101 GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
102
103 if (dir)
104 GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
105 else
106 GPDR1 |= (1 << GPDR1_OFFSET(pin));
107 break;
108 case 3:
109 GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
110
111 if (dir)
112 GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
113 else
114 GPDR1 |= (1 << GPDR1_OFFSET(pin));
115 break;
116 default:
117 printk(KERN_ERR "unimplemented\n");
118 }
119}
120
121static void am200_init_gpio_regs(struct metronomefb_par *par)
122{
123 am200_init_gpio_pin(LED_GPIO_PIN, 0);
124 am200_set_gpio_output(LED_GPIO_PIN, 0);
125
126 am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
127 am200_set_gpio_output(STDBY_GPIO_PIN, 0);
128
129 am200_init_gpio_pin(RST_GPIO_PIN, 0);
130 am200_set_gpio_output(RST_GPIO_PIN, 0);
131
132 am200_init_gpio_pin(RDY_GPIO_PIN, 1);
133
134 am200_init_gpio_pin(ERR_GPIO_PIN, 1);
135
136 am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
137 am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
138}
139
140static void am200_disable_lcd_controller(struct metronomefb_par *par)
141{
142 LCSR = 0xffffffff; /* Clear LCD Status Register */
143 LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
144
145 /* we reset and just wait for things to settle */
146 msleep(200);
147}
148
149static void am200_enable_lcd_controller(struct metronomefb_par *par)
150{
151 LCSR = 0xffffffff;
152 FDADR0 = par->metromem_desc_dma;
153 LCCR0 |= LCCR0_ENB;
154}
155
156static void am200_init_lcdc_regs(struct metronomefb_par *par)
157{
158 /* here we do:
159 - disable the lcd controller
160 - setup lcd control registers
161 - setup dma descriptor
162 - reenable lcd controller
163 */
164
165 /* disable the lcd controller */
166 am200_disable_lcd_controller(par);
167
168 /* setup lcd control registers */
169 LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
170 | LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
171
172 LCCR1 = (par->info->var.xres/2 - 1) /* pixels per line */
173 | (27 << 10) /* hsync pulse width - 1 */
174 | (33 << 16) /* eol pixel count */
175 | (33 << 24); /* bol pixel count */
176
177 LCCR2 = (par->info->var.yres - 1) /* lines per panel */
178 | (24 << 10) /* vsync pulse width - 1 */
179 | (2 << 16) /* eof pixel count */
180 | (0 << 24); /* bof pixel count */
181
182 LCCR3 = 2 /* pixel clock divisor */
183 | (24 << 8) /* AC Bias pin freq */
184 | LCCR3_16BPP /* BPP */
185 | LCCR3_PCP; /* PCP falling edge */
186
187}
188
189static void am200_post_dma_setup(struct metronomefb_par *par)
190{
191 par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
192 par->metromem_desc->mFSADR0 = par->metromem_dma;
193 par->metromem_desc->mFIDR0 = 0;
194 par->metromem_desc->mLDCMD0 = par->info->var.xres
195 * par->info->var.yres;
196 am200_enable_lcd_controller(par);
197}
198
199static void am200_free_irq(struct fb_info *info)
200{
201 free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
202}
203
204static irqreturn_t am200_handle_irq(int irq, void *dev_id)
205{
206 struct fb_info *info = dev_id;
207 struct metronomefb_par *par = info->par;
208
209 wake_up_interruptible(&par->waitq);
210 return IRQ_HANDLED;
211}
212
213static int am200_setup_irq(struct fb_info *info)
214{
215 int retval;
216
217 retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
218 IRQF_DISABLED, "AM200", info);
219 if (retval) {
220 printk(KERN_ERR "am200epd: request_irq failed: %d\n", retval);
221 return retval;
222 }
223
224 return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQT_FALLING);
225}
226
227static void am200_set_rst(struct metronomefb_par *par, int state)
228{
229 am200_set_gpio_output(RST_GPIO_PIN, state);
230}
231
232static void am200_set_stdby(struct metronomefb_par *par, int state)
233{
234 am200_set_gpio_output(STDBY_GPIO_PIN, state);
235}
236
237static int am200_wait_event(struct metronomefb_par *par)
238{
239 return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
240}
241
242static int am200_wait_event_intr(struct metronomefb_par *par)
243{
244 return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
245}
246
247static struct metronome_board am200_board = {
248 .owner = THIS_MODULE,
249 .free_irq = am200_free_irq,
250 .setup_irq = am200_setup_irq,
251 .init_gpio_regs = am200_init_gpio_regs,
252 .init_lcdc_regs = am200_init_lcdc_regs,
253 .post_dma_setup = am200_post_dma_setup,
254 .set_rst = am200_set_rst,
255 .set_stdby = am200_set_stdby,
256 .met_wait_event = am200_wait_event,
257 .met_wait_event_intr = am200_wait_event_intr,
258};
259
260static struct platform_device *am200_device;
261
262static int __init am200_init(void)
263{
264 int ret;
265
266 /* request our platform independent driver */
267 request_module("metronomefb");
268
269 am200_device = platform_device_alloc("metronomefb", -1);
270 if (!am200_device)
271 return -ENOMEM;
272
273 platform_device_add_data(am200_device, &am200_board,
274 sizeof(am200_board));
275
276 /* this _add binds metronomefb to am200. metronomefb refcounts am200 */
277 ret = platform_device_add(am200_device);
278
279 if (ret)
280 platform_device_put(am200_device);
281
282 return ret;
283}
284
285static void __exit am200_exit(void)
286{
287 platform_device_unregister(am200_device);
288}
289
290module_init(am200_init);
291module_exit(am200_exit);
292
293MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
294MODULE_AUTHOR("Jaya Kumar");
295MODULE_LICENSE("GPL");
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 05a328c11a8b..b8e9a8682f2d 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1136,7 +1136,6 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg
1136 * Interface to the low level console driver 1136 * Interface to the low level console driver
1137 */ 1137 */
1138 1138
1139int amifb_init(void);
1140static void amifb_deinit(void); 1139static void amifb_deinit(void);
1141 1140
1142 /* 1141 /*
@@ -2048,13 +2047,16 @@ static void amifb_copyarea(struct fb_info *info,
2048 width = x2 - dx; 2047 width = x2 - dx;
2049 height = y2 - dy; 2048 height = y2 - dy;
2050 2049
2050 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2051 return;
2052
2051 /* update sx,sy */ 2053 /* update sx,sy */
2052 sx = area->sx + (dx - area->dx); 2054 sx = area->sx + (dx - area->dx);
2053 sy = area->sy + (dy - area->dy); 2055 sy = area->sy + (dy - area->dy);
2054 2056
2055 /* the source must be completely inside the virtual screen */ 2057 /* the source must be completely inside the virtual screen */
2056 if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || 2058 if (sx + width > info->var.xres_virtual ||
2057 (sy + height) > info->var.yres_virtual) 2059 sy + height > info->var.yres_virtual)
2058 return; 2060 return;
2059 2061
2060 if (dy > sy || (dy == sy && dx > sx)) { 2062 if (dy > sy || (dy == sy && dx > sx)) {
@@ -2245,7 +2247,7 @@ static inline void chipfree(void)
2245 * Initialisation 2247 * Initialisation
2246 */ 2248 */
2247 2249
2248int __init amifb_init(void) 2250static int __init amifb_init(void)
2249{ 2251{
2250 int tag, i, err = 0; 2252 int tag, i, err = 0;
2251 u_long chipptr; 2253 u_long chipptr;
@@ -2383,6 +2385,9 @@ default_chipset:
2383 goto amifb_error; 2385 goto amifb_error;
2384 } 2386 }
2385 2387
2388 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
2389 &fb_info.modelist);
2390
2386 round_down_bpp = 0; 2391 round_down_bpp = 0;
2387 chipptr = chipalloc(fb_info.fix.smem_len+ 2392 chipptr = chipalloc(fb_info.fix.smem_len+
2388 SPRITEMEMSIZE+ 2393 SPRITEMEMSIZE+
@@ -3787,16 +3792,14 @@ static void ami_rebuild_copper(void)
3787 } 3792 }
3788} 3793}
3789 3794
3790 3795static void __exit amifb_exit(void)
3791module_init(amifb_init);
3792
3793#ifdef MODULE
3794MODULE_LICENSE("GPL");
3795
3796void cleanup_module(void)
3797{ 3796{
3798 unregister_framebuffer(&fb_info); 3797 unregister_framebuffer(&fb_info);
3799 amifb_deinit(); 3798 amifb_deinit();
3800 amifb_video_off(); 3799 amifb_video_off();
3801} 3800}
3802#endif /* MODULE */ 3801
3802module_init(amifb_init);
3803module_exit(amifb_exit);
3804
3805MODULE_LICENSE("GPL");
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index 5001bd4ef466..314d18694b6a 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -11,7 +11,6 @@
11 * Code is based on s3fb 11 * Code is based on s3fb
12 */ 12 */
13 13
14#include <linux/version.h>
15#include <linux/module.h> 14#include <linux/module.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/errno.h> 16#include <linux/errno.h>
@@ -958,20 +957,20 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
958 /* Prepare PCI device */ 957 /* Prepare PCI device */
959 rc = pci_enable_device(dev); 958 rc = pci_enable_device(dev);
960 if (rc < 0) { 959 if (rc < 0) {
961 dev_err(info->dev, "cannot enable PCI device\n"); 960 dev_err(info->device, "cannot enable PCI device\n");
962 goto err_enable_device; 961 goto err_enable_device;
963 } 962 }
964 963
965 rc = pci_request_regions(dev, "arkfb"); 964 rc = pci_request_regions(dev, "arkfb");
966 if (rc < 0) { 965 if (rc < 0) {
967 dev_err(info->dev, "cannot reserve framebuffer region\n"); 966 dev_err(info->device, "cannot reserve framebuffer region\n");
968 goto err_request_regions; 967 goto err_request_regions;
969 } 968 }
970 969
971 par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info); 970 par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
972 if (! par->dac) { 971 if (! par->dac) {
973 rc = -ENOMEM; 972 rc = -ENOMEM;
974 dev_err(info->dev, "RAMDAC initialization failed\n"); 973 dev_err(info->device, "RAMDAC initialization failed\n");
975 goto err_dac; 974 goto err_dac;
976 } 975 }
977 976
@@ -982,7 +981,7 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
982 info->screen_base = pci_iomap(dev, 0, 0); 981 info->screen_base = pci_iomap(dev, 0, 0);
983 if (! info->screen_base) { 982 if (! info->screen_base) {
984 rc = -ENOMEM; 983 rc = -ENOMEM;
985 dev_err(info->dev, "iomap for framebuffer failed\n"); 984 dev_err(info->device, "iomap for framebuffer failed\n");
986 goto err_iomap; 985 goto err_iomap;
987 } 986 }
988 987
@@ -1004,19 +1003,19 @@ static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_
1004 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); 1003 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
1005 if (! ((rc == 1) || (rc == 2))) { 1004 if (! ((rc == 1) || (rc == 2))) {
1006 rc = -EINVAL; 1005 rc = -EINVAL;
1007 dev_err(info->dev, "mode %s not found\n", mode_option); 1006 dev_err(info->device, "mode %s not found\n", mode_option);
1008 goto err_find_mode; 1007 goto err_find_mode;
1009 } 1008 }
1010 1009
1011 rc = fb_alloc_cmap(&info->cmap, 256, 0); 1010 rc = fb_alloc_cmap(&info->cmap, 256, 0);
1012 if (rc < 0) { 1011 if (rc < 0) {
1013 dev_err(info->dev, "cannot allocate colormap\n"); 1012 dev_err(info->device, "cannot allocate colormap\n");
1014 goto err_alloc_cmap; 1013 goto err_alloc_cmap;
1015 } 1014 }
1016 1015
1017 rc = register_framebuffer(info); 1016 rc = register_framebuffer(info);
1018 if (rc < 0) { 1017 if (rc < 0) {
1019 dev_err(info->dev, "cannot register framebugger\n"); 1018 dev_err(info->device, "cannot register framebugger\n");
1020 goto err_reg_fb; 1019 goto err_reg_fb;
1021 } 1020 }
1022 1021
@@ -1090,7 +1089,7 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
1090 struct fb_info *info = pci_get_drvdata(dev); 1089 struct fb_info *info = pci_get_drvdata(dev);
1091 struct arkfb_info *par = info->par; 1090 struct arkfb_info *par = info->par;
1092 1091
1093 dev_info(info->dev, "suspend\n"); 1092 dev_info(info->device, "suspend\n");
1094 1093
1095 acquire_console_sem(); 1094 acquire_console_sem();
1096 mutex_lock(&(par->open_lock)); 1095 mutex_lock(&(par->open_lock));
@@ -1121,16 +1120,13 @@ static int ark_pci_resume (struct pci_dev* dev)
1121 struct fb_info *info = pci_get_drvdata(dev); 1120 struct fb_info *info = pci_get_drvdata(dev);
1122 struct arkfb_info *par = info->par; 1121 struct arkfb_info *par = info->par;
1123 1122
1124 dev_info(info->dev, "resume\n"); 1123 dev_info(info->device, "resume\n");
1125 1124
1126 acquire_console_sem(); 1125 acquire_console_sem();
1127 mutex_lock(&(par->open_lock)); 1126 mutex_lock(&(par->open_lock));
1128 1127
1129 if (par->ref_count == 0) { 1128 if (par->ref_count == 0)
1130 mutex_unlock(&(par->open_lock)); 1129 goto fail;
1131 release_console_sem();
1132 return 0;
1133 }
1134 1130
1135 pci_set_power_state(dev, PCI_D0); 1131 pci_set_power_state(dev, PCI_D0);
1136 pci_restore_state(dev); 1132 pci_restore_state(dev);
@@ -1143,8 +1139,8 @@ static int ark_pci_resume (struct pci_dev* dev)
1143 arkfb_set_par(info); 1139 arkfb_set_par(info);
1144 fb_set_suspend(info, 0); 1140 fb_set_suspend(info, 0);
1145 1141
1146 mutex_unlock(&(par->open_lock));
1147fail: 1142fail:
1143 mutex_unlock(&(par->open_lock));
1148 release_console_sem(); 1144 release_console_sem();
1149 return 0; 1145 return 0;
1150} 1146}
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index dff35474b854..77eb8b34fbfa 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2593,13 +2593,16 @@ static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
2593 width = x2 - dx; 2593 width = x2 - dx;
2594 height = y2 - dy; 2594 height = y2 - dy;
2595 2595
2596 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2597 return;
2598
2596 /* update sx,sy */ 2599 /* update sx,sy */
2597 sx = area->sx + (dx - area->dx); 2600 sx = area->sx + (dx - area->dx);
2598 sy = area->sy + (dy - area->dy); 2601 sy = area->sy + (dy - area->dy);
2599 2602
2600 /* the source must be completely inside the virtual screen */ 2603 /* the source must be completely inside the virtual screen */
2601 if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || 2604 if (sx + width > info->var.xres_virtual ||
2602 (sy + height) > info->var.yres_virtual) 2605 sy + height > info->var.yres_virtual)
2603 return; 2606 return;
2604 2607
2605 if (dy > sy || (dy == sy && dx > sx)) { 2608 if (dy > sy || (dy == sy && dx > sx)) {
@@ -3110,7 +3113,7 @@ int __init atafb_init(void)
3110 printk("atafb_init: start\n"); 3113 printk("atafb_init: start\n");
3111 3114
3112 if (!MACH_IS_ATARI) 3115 if (!MACH_IS_ATARI)
3113 return -ENXIO; 3116 return -ENODEV;
3114 3117
3115 do { 3118 do {
3116#ifdef ATAFB_EXT 3119#ifdef ATAFB_EXT
@@ -3230,6 +3233,9 @@ int __init atafb_init(void)
3230 return -EINVAL; 3233 return -EINVAL;
3231 } 3234 }
3232 3235
3236 fb_videomode_to_modelist(atafb_modedb, NUM_TOTAL_MODES,
3237 &fb_info.modelist);
3238
3233 atafb_set_disp(&fb_info); 3239 atafb_set_disp(&fb_info);
3234 3240
3235 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0); 3241 fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index b004036d4087..f8d0a57a07cb 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -18,9 +18,9 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/backlight.h> 19#include <linux/backlight.h>
20 20
21#include <asm/arch/board.h> 21#include <mach/board.h>
22#include <asm/arch/cpu.h> 22#include <mach/cpu.h>
23#include <asm/arch/gpio.h> 23#include <mach/gpio.h>
24 24
25#include <video/atmel_lcdc.h> 25#include <video/atmel_lcdc.h>
26 26
@@ -39,7 +39,9 @@
39#endif 39#endif
40 40
41#if defined(CONFIG_ARCH_AT91) 41#if defined(CONFIG_ARCH_AT91)
42#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT 42#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
43 | FBINFO_PARTIAL_PAN_OK \
44 | FBINFO_HWACCEL_YPAN)
43 45
44static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, 46static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
45 struct fb_var_screeninfo *var) 47 struct fb_var_screeninfo *var)
@@ -177,7 +179,7 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
177 .type = FB_TYPE_PACKED_PIXELS, 179 .type = FB_TYPE_PACKED_PIXELS,
178 .visual = FB_VISUAL_TRUECOLOR, 180 .visual = FB_VISUAL_TRUECOLOR,
179 .xpanstep = 0, 181 .xpanstep = 0,
180 .ypanstep = 0, 182 .ypanstep = 1,
181 .ywrapstep = 0, 183 .ywrapstep = 0,
182 .accel = FB_ACCEL_NONE, 184 .accel = FB_ACCEL_NONE,
183}; 185};
@@ -206,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
206 return value; 208 return value;
207} 209}
208 210
211static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
212{
213 /* Turn off the LCD controller and the DMA controller */
214 lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
215 sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
216
217 /* Wait for the LCDC core to become idle */
218 while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
219 msleep(10);
220
221 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
222}
223
224static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
225{
226 atmel_lcdfb_stop_nowait(sinfo);
227
228 /* Wait for DMA engine to become idle... */
229 while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
230 msleep(10);
231}
232
233static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
234{
235 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
236 lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
237 (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
238 | ATMEL_LCDC_PWR);
239}
240
209static void atmel_lcdfb_update_dma(struct fb_info *info, 241static void atmel_lcdfb_update_dma(struct fb_info *info,
210 struct fb_var_screeninfo *var) 242 struct fb_var_screeninfo *var)
211{ 243{
@@ -240,9 +272,11 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
240{ 272{
241 struct fb_info *info = sinfo->info; 273 struct fb_info *info = sinfo->info;
242 struct fb_var_screeninfo *var = &info->var; 274 struct fb_var_screeninfo *var = &info->var;
275 unsigned int smem_len;
243 276
244 info->fix.smem_len = (var->xres_virtual * var->yres_virtual 277 smem_len = (var->xres_virtual * var->yres_virtual
245 * ((var->bits_per_pixel + 7) / 8)); 278 * ((var->bits_per_pixel + 7) / 8));
279 info->fix.smem_len = max(smem_len, sinfo->smem_len);
246 280
247 info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, 281 info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
248 (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); 282 (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
@@ -256,6 +290,20 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
256 return 0; 290 return 0;
257} 291}
258 292
293static const struct fb_videomode *atmel_lcdfb_choose_mode(struct fb_var_screeninfo *var,
294 struct fb_info *info)
295{
296 struct fb_videomode varfbmode;
297 const struct fb_videomode *fbmode = NULL;
298
299 fb_var_to_videomode(&varfbmode, var);
300 fbmode = fb_find_nearest_mode(&varfbmode, &info->modelist);
301 if (fbmode)
302 fb_videomode_to_var(var, fbmode);
303 return fbmode;
304}
305
306
259/** 307/**
260 * atmel_lcdfb_check_var - Validates a var passed in. 308 * atmel_lcdfb_check_var - Validates a var passed in.
261 * @var: frame buffer variable screen structure 309 * @var: frame buffer variable screen structure
@@ -289,6 +337,15 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
289 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; 337 clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
290 338
291 dev_dbg(dev, "%s:\n", __func__); 339 dev_dbg(dev, "%s:\n", __func__);
340
341 if (!(var->pixclock && var->bits_per_pixel)) {
342 /* choose a suitable mode if possible */
343 if (!atmel_lcdfb_choose_mode(var, info)) {
344 dev_err(dev, "needed value not specified\n");
345 return -EINVAL;
346 }
347 }
348
292 dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres); 349 dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
293 dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock)); 350 dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
294 dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel); 351 dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
@@ -299,6 +356,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
299 return -EINVAL; 356 return -EINVAL;
300 } 357 }
301 358
359 /* Do not allow to have real resoulution larger than virtual */
360 if (var->xres > var->xres_virtual)
361 var->xres_virtual = var->xres;
362
363 if (var->yres > var->yres_virtual)
364 var->yres_virtual = var->yres;
365
302 /* Force same alignment for each line */ 366 /* Force same alignment for each line */
303 var->xres = (var->xres + 3) & ~3UL; 367 var->xres = (var->xres + 3) & ~3UL;
304 var->xres_virtual = (var->xres_virtual + 3) & ~3UL; 368 var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
@@ -308,6 +372,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
308 var->transp.offset = var->transp.length = 0; 372 var->transp.offset = var->transp.length = 0;
309 var->xoffset = var->yoffset = 0; 373 var->xoffset = var->yoffset = 0;
310 374
375 if (info->fix.smem_len) {
376 unsigned int smem_len = (var->xres_virtual * var->yres_virtual
377 * ((var->bits_per_pixel + 7) / 8));
378 if (smem_len > info->fix.smem_len)
379 return -EINVAL;
380 }
381
311 /* Saturate vertical and horizontal timings at maximum values */ 382 /* Saturate vertical and horizontal timings at maximum values */
312 var->vsync_len = min_t(u32, var->vsync_len, 383 var->vsync_len = min_t(u32, var->vsync_len,
313 (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); 384 (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
@@ -344,6 +415,10 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
344 var->red.offset = 11; 415 var->red.offset = 11;
345 var->blue.offset = 0; 416 var->blue.offset = 0;
346 var->green.length = 6; 417 var->green.length = 6;
418 } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) {
419 var->red.offset = 10;
420 var->blue.offset = 0;
421 var->green.length = 5;
347 } else { 422 } else {
348 /* BGR:555 mode */ 423 /* BGR:555 mode */
349 var->red.offset = 0; 424 var->red.offset = 0;
@@ -379,6 +454,17 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
379 return 0; 454 return 0;
380} 455}
381 456
457/*
458 * LCD reset sequence
459 */
460static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
461{
462 might_sleep();
463
464 atmel_lcdfb_stop(sinfo);
465 atmel_lcdfb_start(sinfo);
466}
467
382/** 468/**
383 * atmel_lcdfb_set_par - Alters the hardware state. 469 * atmel_lcdfb_set_par - Alters the hardware state.
384 * @info: frame buffer structure that represents a single frame buffer 470 * @info: frame buffer structure that represents a single frame buffer
@@ -401,19 +487,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
401 unsigned long clk_value_khz; 487 unsigned long clk_value_khz;
402 unsigned long bits_per_line; 488 unsigned long bits_per_line;
403 489
490 might_sleep();
491
404 dev_dbg(info->device, "%s:\n", __func__); 492 dev_dbg(info->device, "%s:\n", __func__);
405 dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n", 493 dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
406 info->var.xres, info->var.yres, 494 info->var.xres, info->var.yres,
407 info->var.xres_virtual, info->var.yres_virtual); 495 info->var.xres_virtual, info->var.yres_virtual);
408 496
409 /* Turn off the LCD controller and the DMA controller */ 497 atmel_lcdfb_stop_nowait(sinfo);
410 lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
411
412 /* Wait for the LCDC core to become idle */
413 while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
414 msleep(10);
415
416 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
417 498
418 if (info->var.bits_per_pixel == 1) 499 if (info->var.bits_per_pixel == 1)
419 info->fix.visual = FB_VISUAL_MONO01; 500 info->fix.visual = FB_VISUAL_MONO01;
@@ -511,18 +592,14 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
511 592
512 /* Disable all interrupts */ 593 /* Disable all interrupts */
513 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); 594 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
595 /* Enable FIFO & DMA errors */
596 lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
514 597
515 /* ...wait for DMA engine to become idle... */ 598 /* ...wait for DMA engine to become idle... */
516 while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) 599 while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
517 msleep(10); 600 msleep(10);
518 601
519 dev_dbg(info->device, " * re-enable DMA engine\n"); 602 atmel_lcdfb_start(sinfo);
520 /* ...and enable it with updated configuration */
521 lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
522
523 dev_dbg(info->device, " * re-enable LCDC core\n");
524 lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
525 (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
526 603
527 dev_dbg(info->device, " * DONE\n"); 604 dev_dbg(info->device, " * DONE\n");
528 605
@@ -645,10 +722,26 @@ static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
645 u32 status; 722 u32 status;
646 723
647 status = lcdc_readl(sinfo, ATMEL_LCDC_ISR); 724 status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
648 lcdc_writel(sinfo, ATMEL_LCDC_IDR, status); 725 if (status & ATMEL_LCDC_UFLWI) {
726 dev_warn(info->device, "FIFO underflow %#x\n", status);
727 /* reset DMA and FIFO to avoid screen shifting */
728 schedule_work(&sinfo->task);
729 }
730 lcdc_writel(sinfo, ATMEL_LCDC_ICR, status);
649 return IRQ_HANDLED; 731 return IRQ_HANDLED;
650} 732}
651 733
734/*
735 * LCD controller task (to reset the LCD)
736 */
737static void atmel_lcdfb_task(struct work_struct *work)
738{
739 struct atmel_lcdfb_info *sinfo =
740 container_of(work, struct atmel_lcdfb_info, task);
741
742 atmel_lcdfb_reset(sinfo);
743}
744
652static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) 745static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
653{ 746{
654 struct fb_info *info = sinfo->info; 747 struct fb_info *info = sinfo->info;
@@ -691,6 +784,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
691 struct fb_info *info; 784 struct fb_info *info;
692 struct atmel_lcdfb_info *sinfo; 785 struct atmel_lcdfb_info *sinfo;
693 struct atmel_lcdfb_info *pdata_sinfo; 786 struct atmel_lcdfb_info *pdata_sinfo;
787 struct fb_videomode fbmode;
694 struct resource *regs = NULL; 788 struct resource *regs = NULL;
695 struct resource *map = NULL; 789 struct resource *map = NULL;
696 int ret; 790 int ret;
@@ -714,6 +808,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
714 sinfo->default_monspecs = pdata_sinfo->default_monspecs; 808 sinfo->default_monspecs = pdata_sinfo->default_monspecs;
715 sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; 809 sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
716 sinfo->guard_time = pdata_sinfo->guard_time; 810 sinfo->guard_time = pdata_sinfo->guard_time;
811 sinfo->smem_len = pdata_sinfo->smem_len;
717 sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; 812 sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
718 sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode; 813 sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
719 } else { 814 } else {
@@ -824,6 +919,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
824 goto unmap_mmio; 919 goto unmap_mmio;
825 } 920 }
826 921
922 /* Some operations on the LCDC might sleep and
923 * require a preemptible task context */
924 INIT_WORK(&sinfo->task, atmel_lcdfb_task);
925
827 ret = atmel_lcdfb_init_fbinfo(sinfo); 926 ret = atmel_lcdfb_init_fbinfo(sinfo);
828 if (ret < 0) { 927 if (ret < 0) {
829 dev_err(dev, "init fbinfo failed: %d\n", ret); 928 dev_err(dev, "init fbinfo failed: %d\n", ret);
@@ -850,9 +949,13 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
850 ret = register_framebuffer(info); 949 ret = register_framebuffer(info);
851 if (ret < 0) { 950 if (ret < 0) {
852 dev_err(dev, "failed to register framebuffer device: %d\n", ret); 951 dev_err(dev, "failed to register framebuffer device: %d\n", ret);
853 goto free_cmap; 952 goto reset_drvdata;
854 } 953 }
855 954
955 /* add selected videomode to modelist */
956 fb_var_to_videomode(&fbmode, &info->var);
957 fb_add_videomode(&fbmode, &info->modelist);
958
856 /* Power up the LCDC screen */ 959 /* Power up the LCDC screen */
857 if (sinfo->atmel_lcdfb_power_control) 960 if (sinfo->atmel_lcdfb_power_control)
858 sinfo->atmel_lcdfb_power_control(1); 961 sinfo->atmel_lcdfb_power_control(1);
@@ -862,10 +965,12 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
862 965
863 return 0; 966 return 0;
864 967
865 968reset_drvdata:
969 dev_set_drvdata(dev, NULL);
866free_cmap: 970free_cmap:
867 fb_dealloc_cmap(&info->cmap); 971 fb_dealloc_cmap(&info->cmap);
868unregister_irqs: 972unregister_irqs:
973 cancel_work_sync(&sinfo->task);
869 free_irq(sinfo->irq_base, info); 974 free_irq(sinfo->irq_base, info);
870unmap_mmio: 975unmap_mmio:
871 exit_backlight(sinfo); 976 exit_backlight(sinfo);
@@ -898,11 +1003,13 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
898{ 1003{
899 struct device *dev = &pdev->dev; 1004 struct device *dev = &pdev->dev;
900 struct fb_info *info = dev_get_drvdata(dev); 1005 struct fb_info *info = dev_get_drvdata(dev);
901 struct atmel_lcdfb_info *sinfo = info->par; 1006 struct atmel_lcdfb_info *sinfo;
902 1007
903 if (!sinfo) 1008 if (!info || !info->par)
904 return 0; 1009 return 0;
1010 sinfo = info->par;
905 1011
1012 cancel_work_sync(&sinfo->task);
906 exit_backlight(sinfo); 1013 exit_backlight(sinfo);
907 if (sinfo->atmel_lcdfb_power_control) 1014 if (sinfo->atmel_lcdfb_power_control)
908 sinfo->atmel_lcdfb_power_control(0); 1015 sinfo->atmel_lcdfb_power_control(0);
@@ -935,11 +1042,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
935 struct fb_info *info = platform_get_drvdata(pdev); 1042 struct fb_info *info = platform_get_drvdata(pdev);
936 struct atmel_lcdfb_info *sinfo = info->par; 1043 struct atmel_lcdfb_info *sinfo = info->par;
937 1044
1045 /*
1046 * We don't want to handle interrupts while the clock is
1047 * stopped. It may take forever.
1048 */
1049 lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
1050
938 sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); 1051 sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
939 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0); 1052 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
940 if (sinfo->atmel_lcdfb_power_control) 1053 if (sinfo->atmel_lcdfb_power_control)
941 sinfo->atmel_lcdfb_power_control(0); 1054 sinfo->atmel_lcdfb_power_control(0);
1055
1056 atmel_lcdfb_stop(sinfo);
942 atmel_lcdfb_stop_clock(sinfo); 1057 atmel_lcdfb_stop_clock(sinfo);
1058
943 return 0; 1059 return 0;
944} 1060}
945 1061
@@ -949,9 +1065,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
949 struct atmel_lcdfb_info *sinfo = info->par; 1065 struct atmel_lcdfb_info *sinfo = info->par;
950 1066
951 atmel_lcdfb_start_clock(sinfo); 1067 atmel_lcdfb_start_clock(sinfo);
1068 atmel_lcdfb_start(sinfo);
952 if (sinfo->atmel_lcdfb_power_control) 1069 if (sinfo->atmel_lcdfb_power_control)
953 sinfo->atmel_lcdfb_power_control(1); 1070 sinfo->atmel_lcdfb_power_control(1);
954 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon); 1071 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
1072
1073 /* Enable FIFO & DMA errors */
1074 lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
1075 | ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
1076
955 return 0; 1077 return 0;
956} 1078}
957 1079
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 24ee96c4e9e9..243ea4ab20c8 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1339,10 +1339,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
1339 if (vclk * 12 < c.ppll_min) 1339 if (vclk * 12 < c.ppll_min)
1340 vclk = c.ppll_min/12; 1340 vclk = c.ppll_min/12;
1341 1341
1342 pll->post_divider = -1;
1343
1344 /* now, find an acceptable divider */ 1342 /* now, find an acceptable divider */
1345 for (i = 0; i < sizeof(post_dividers); i++) { 1343 for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
1346 output_freq = post_dividers[i] * vclk; 1344 output_freq = post_dividers[i] * vclk;
1347 if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) { 1345 if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
1348 pll->post_divider = post_dividers[i]; 1346 pll->post_divider = post_dividers[i];
@@ -1350,7 +1348,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
1350 } 1348 }
1351 } 1349 }
1352 1350
1353 if (pll->post_divider < 0) 1351 if (i == ARRAY_SIZE(post_dividers))
1354 return -EINVAL; 1352 return -EINVAL;
1355 1353
1356 /* calculate feedback divider */ 1354 /* calculate feedback divider */
@@ -1872,7 +1870,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
1872 struct fb_info *info = pci_get_drvdata(pdev); 1870 struct fb_info *info = pci_get_drvdata(pdev);
1873 struct aty128fb_par *par = info->par; 1871 struct aty128fb_par *par = info->par;
1874 struct fb_var_screeninfo var; 1872 struct fb_var_screeninfo var;
1875 char video_card[DEVICE_NAME_SIZE]; 1873 char video_card[50];
1876 u8 chip_rev; 1874 u8 chip_rev;
1877 u32 dac; 1875 u32 dac;
1878 1876
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index bd4ac0bafecb..cc6b470073da 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -244,7 +244,7 @@ static int atyfb_sync(struct fb_info *info);
244 */ 244 */
245 245
246static int aty_init(struct fb_info *info); 246static int aty_init(struct fb_info *info);
247static void aty_resume_chip(struct fb_info *info); 247
248#ifdef CONFIG_ATARI 248#ifdef CONFIG_ATARI
249static int store_video_par(char *videopar, unsigned char m64_num); 249static int store_video_par(char *videopar, unsigned char m64_num);
250#endif 250#endif
@@ -424,7 +424,6 @@ static struct {
424#endif /* CONFIG_FB_ATY_CT */ 424#endif /* CONFIG_FB_ATY_CT */
425}; 425};
426 426
427/* can not fail */
428static int __devinit correct_chipset(struct atyfb_par *par) 427static int __devinit correct_chipset(struct atyfb_par *par)
429{ 428{
430 u8 rev; 429 u8 rev;
@@ -437,6 +436,9 @@ static int __devinit correct_chipset(struct atyfb_par *par)
437 if (par->pci_id == aty_chips[i].pci_id) 436 if (par->pci_id == aty_chips[i].pci_id)
438 break; 437 break;
439 438
439 if (i < 0)
440 return -ENODEV;
441
440 name = aty_chips[i].name; 442 name = aty_chips[i].name;
441 par->pll_limits.pll_max = aty_chips[i].pll; 443 par->pll_limits.pll_max = aty_chips[i].pll;
442 par->pll_limits.mclk = aty_chips[i].mclk; 444 par->pll_limits.mclk = aty_chips[i].mclk;
@@ -2021,6 +2023,20 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2021 return 0; 2023 return 0;
2022} 2024}
2023 2025
2026static void aty_resume_chip(struct fb_info *info)
2027{
2028 struct atyfb_par *par = info->par;
2029
2030 aty_st_le32(MEM_CNTL, par->mem_cntl, par);
2031
2032 if (par->pll_ops->resume_pll)
2033 par->pll_ops->resume_pll(info, &par->pll);
2034
2035 if (par->aux_start)
2036 aty_st_le32(BUS_CNTL,
2037 aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2038}
2039
2024static int atyfb_pci_resume(struct pci_dev *pdev) 2040static int atyfb_pci_resume(struct pci_dev *pdev)
2025{ 2041{
2026 struct fb_info *info = pci_get_drvdata(pdev); 2042 struct fb_info *info = pci_get_drvdata(pdev);
@@ -2229,6 +2245,7 @@ static int __devinit aty_init(struct fb_info *info)
2229 const char *ramname = NULL, *xtal; 2245 const char *ramname = NULL, *xtal;
2230 int gtb_memsize, has_var = 0; 2246 int gtb_memsize, has_var = 0;
2231 struct fb_var_screeninfo var; 2247 struct fb_var_screeninfo var;
2248 int ret;
2232 2249
2233 init_waitqueue_head(&par->vblank.wait); 2250 init_waitqueue_head(&par->vblank.wait);
2234 spin_lock_init(&par->int_lock); 2251 spin_lock_init(&par->int_lock);
@@ -2610,7 +2627,8 @@ static int __devinit aty_init(struct fb_info *info)
2610 var.yres_virtual = var.yres; 2627 var.yres_virtual = var.yres;
2611 } 2628 }
2612 2629
2613 if (atyfb_check_var(&var, info)) { 2630 ret = atyfb_check_var(&var, info);
2631 if (ret) {
2614 PRINTKE("can't set default video mode\n"); 2632 PRINTKE("can't set default video mode\n");
2615 goto aty_init_exit; 2633 goto aty_init_exit;
2616 } 2634 }
@@ -2621,10 +2639,12 @@ static int __devinit aty_init(struct fb_info *info)
2621#endif /* CONFIG_FB_ATY_CT */ 2639#endif /* CONFIG_FB_ATY_CT */
2622 info->var = var; 2640 info->var = var;
2623 2641
2624 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) 2642 ret = fb_alloc_cmap(&info->cmap, 256, 0);
2643 if (ret < 0)
2625 goto aty_init_exit; 2644 goto aty_init_exit;
2626 2645
2627 if (register_framebuffer(info) < 0) { 2646 ret = register_framebuffer(info);
2647 if (ret < 0) {
2628 fb_dealloc_cmap(&info->cmap); 2648 fb_dealloc_cmap(&info->cmap);
2629 goto aty_init_exit; 2649 goto aty_init_exit;
2630 } 2650 }
@@ -2650,20 +2670,7 @@ aty_init_exit:
2650 par->mtrr_aper = -1; 2670 par->mtrr_aper = -1;
2651 } 2671 }
2652#endif 2672#endif
2653 return -1; 2673 return ret;
2654}
2655
2656static void aty_resume_chip(struct fb_info *info)
2657{
2658 struct atyfb_par *par = info->par;
2659
2660 aty_st_le32(MEM_CNTL, par->mem_cntl, par);
2661
2662 if (par->pll_ops->resume_pll)
2663 par->pll_ops->resume_pll(info, &par->pll);
2664
2665 if (par->aux_start)
2666 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2667} 2674}
2668 2675
2669#ifdef CONFIG_ATARI 2676#ifdef CONFIG_ATARI
@@ -2709,8 +2716,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
2709 if (par->lock_blank || par->asleep) 2716 if (par->lock_blank || par->asleep)
2710 return 0; 2717 return 0;
2711 2718
2712#ifdef CONFIG_FB_ATY_BACKLIGHT 2719#ifdef CONFIG_FB_ATY_GENERIC_LCD
2713#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2714 if (par->lcd_table && blank > FB_BLANK_NORMAL && 2720 if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2715 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2721 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2716 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); 2722 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -2739,8 +2745,7 @@ static int atyfb_blank(int blank, struct fb_info *info)
2739 } 2745 }
2740 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); 2746 aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2741 2747
2742#ifdef CONFIG_FB_ATY_BACKLIGHT 2748#ifdef CONFIG_FB_ATY_GENERIC_LCD
2743#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2744 if (par->lcd_table && blank <= FB_BLANK_NORMAL && 2749 if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2745 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) { 2750 (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2746 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par); 2751 u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -3331,7 +3336,7 @@ static int __devinit init_from_bios(struct atyfb_par *par)
3331 PRINTKE("no BIOS frequency table found, use parameters\n"); 3336 PRINTKE("no BIOS frequency table found, use parameters\n");
3332 ret = -ENXIO; 3337 ret = -ENXIO;
3333 } 3338 }
3334 iounmap((void* __iomem )bios_base); 3339 iounmap((void __iomem *)bios_base);
3335 3340
3336 return ret; 3341 return ret;
3337} 3342}
@@ -3418,14 +3423,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3418 struct fb_info *info; 3423 struct fb_info *info;
3419 struct resource *rp; 3424 struct resource *rp;
3420 struct atyfb_par *par; 3425 struct atyfb_par *par;
3421 int i, rc = -ENOMEM; 3426 int rc = -ENOMEM;
3422
3423 for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
3424 if (pdev->device == aty_chips[i].pci_id)
3425 break;
3426
3427 if (i < 0)
3428 return -ENODEV;
3429 3427
3430 /* Enable device in PCI config */ 3428 /* Enable device in PCI config */
3431 if (pci_enable_device(pdev)) { 3429 if (pci_enable_device(pdev)) {
@@ -3456,7 +3454,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3456 par = info->par; 3454 par = info->par;
3457 info->fix = atyfb_fix; 3455 info->fix = atyfb_fix;
3458 info->device = &pdev->dev; 3456 info->device = &pdev->dev;
3459 par->pci_id = aty_chips[i].pci_id; 3457 par->pci_id = pdev->device;
3460 par->res_start = res_start; 3458 par->res_start = res_start;
3461 par->res_size = res_size; 3459 par->res_size = res_size;
3462 par->irq = pdev->irq; 3460 par->irq = pdev->irq;
@@ -3474,7 +3472,8 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
3474 pci_set_drvdata(pdev, info); 3472 pci_set_drvdata(pdev, info);
3475 3473
3476 /* Init chip & register framebuffer */ 3474 /* Init chip & register framebuffer */
3477 if (aty_init(info)) 3475 rc = aty_init(info);
3476 if (rc)
3478 goto err_release_io; 3477 goto err_release_io;
3479 3478
3480#ifdef __sparc__ 3479#ifdef __sparc__
@@ -3655,18 +3654,62 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
3655 atyfb_remove(info); 3654 atyfb_remove(info);
3656} 3655}
3657 3656
3658/*
3659 * This driver uses its own matching table. That will be more difficult
3660 * to fix, so for now, we just match against any ATI ID and let the
3661 * probe() function find out what's up. That also mean we don't have
3662 * a module ID table though.
3663 */
3664static struct pci_device_id atyfb_pci_tbl[] = { 3657static struct pci_device_id atyfb_pci_tbl[] = {
3665 { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 3658#ifdef CONFIG_FB_ATY_GX
3666 PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 }, 3659 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GX) },
3667 { 0, } 3660 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CX) },
3661#endif /* CONFIG_FB_ATY_GX */
3662
3663#ifdef CONFIG_FB_ATY_CT
3664 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64CT) },
3665 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64ET) },
3666
3667 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LT) },
3668
3669 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VT) },
3670 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GT) },
3671
3672 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VU) },
3673 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GU) },
3674
3675 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LG) },
3676
3677 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64VV) },
3678
3679 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GV) },
3680 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GW) },
3681 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GY) },
3682 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GZ) },
3683
3684 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GB) },
3685 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GD) },
3686 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GI) },
3687 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GP) },
3688 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GQ) },
3689
3690 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LB) },
3691 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LD) },
3692 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LI) },
3693 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LP) },
3694 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LQ) },
3695
3696 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GM) },
3697 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GN) },
3698 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GO) },
3699 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GL) },
3700 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GR) },
3701 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64GS) },
3702
3703 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LM) },
3704 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LN) },
3705 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LR) },
3706 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_CHIP_MACH64LS) },
3707#endif /* CONFIG_FB_ATY_CT */
3708 { }
3668}; 3709};
3669 3710
3711MODULE_DEVICE_TABLE(pci, atyfb_pci_tbl);
3712
3670static struct pci_driver atyfb_driver = { 3713static struct pci_driver atyfb_driver = {
3671 .name = "atyfb", 3714 .name = "atyfb",
3672 .id_table = atyfb_pci_tbl, 3715 .id_table = atyfb_pci_tbl,
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index 3ca27cb13caa..8718f7349d6b 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -5,57 +5,61 @@
5 * --dte 5 * --dte
6 */ 6 */
7 7
8static void radeon_fixup_offset(struct radeonfb_info *rinfo) 8#define FLUSH_CACHE_WORKAROUND 1
9
10void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries)
9{ 11{
10 u32 local_base; 12 int i;
11
12 /* *** Ugly workaround *** */
13 /*
14 * On some platforms, the video memory is mapped at 0 in radeon chip space
15 * (like PPCs) by the firmware. X will always move it up so that it's seen
16 * by the chip to be at the same address as the PCI BAR.
17 * That means that when switching back from X, there is a mismatch between
18 * the offsets programmed into the engine. This means that potentially,
19 * accel operations done before radeonfb has a chance to re-init the engine
20 * will have incorrect offsets, and potentially trash system memory !
21 *
22 * The correct fix is for fbcon to never call any accel op before the engine
23 * has properly been re-initialized (by a call to set_var), but this is a
24 * complex fix. This workaround in the meantime, called before every accel
25 * operation, makes sure the offsets are in sync.
26 */
27 13
28 radeon_fifo_wait (1); 14 for (i=0; i<2000000; i++) {
29 local_base = INREG(MC_FB_LOCATION) << 16; 15 rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f;
30 if (local_base == rinfo->fb_local_base) 16 if (rinfo->fifo_free >= entries)
31 return; 17 return;
18 udelay(10);
19 }
20 printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
21 /* XXX Todo: attempt to reset the engine */
22}
32 23
33 rinfo->fb_local_base = local_base; 24static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
25{
26 if (entries <= rinfo->fifo_free)
27 rinfo->fifo_free -= entries;
28 else
29 radeon_fifo_update_and_wait(rinfo, entries);
30}
34 31
35 radeon_fifo_wait (3); 32static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg,
36 OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | 33 u32 *cache, u32 new_val)
37 (rinfo->fb_local_base >> 10)); 34{
38 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 35 if (new_val == *cache)
39 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 36 return;
37 *cache = new_val;
38 radeon_fifo_wait(rinfo, 1);
39 OUTREG(reg, new_val);
40} 40}
41 41
42static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 42static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo,
43 const struct fb_fillrect *region) 43 const struct fb_fillrect *region)
44{ 44{
45 radeon_fifo_wait(4); 45 radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
46 46 rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P);
47 OUTREG(DP_GUI_MASTER_CNTL, 47 radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
48 rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ 48 DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
49 | GMC_BRUSH_SOLID_COLOR 49 radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache,
50 | ROP3_P); 50 region->color);
51 if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) 51
52 OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); 52 /* Ensure the dst cache is flushed and the engine idle before
53 else 53 * issuing the operation.
54 OUTREG(DP_BRUSH_FRGD_CLR, region->color); 54 *
55 OUTREG(DP_WRITE_MSK, 0xffffffff); 55 * This works around engine lockups on some cards
56 OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); 56 */
57 57#if FLUSH_CACHE_WORKAROUND
58 radeon_fifo_wait(2); 58 radeon_fifo_wait(rinfo, 2);
59 OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
60 OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
61#endif
62 radeon_fifo_wait(rinfo, 2);
59 OUTREG(DST_Y_X, (region->dy << 16) | region->dx); 63 OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
60 OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); 64 OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
61} 65}
@@ -66,15 +70,14 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
66 struct fb_fillrect modded; 70 struct fb_fillrect modded;
67 int vxres, vyres; 71 int vxres, vyres;
68 72
69 if (info->state != FBINFO_STATE_RUNNING) 73 WARN_ON(rinfo->gfx_mode);
74 if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
70 return; 75 return;
71 if (info->flags & FBINFO_HWACCEL_DISABLED) { 76 if (info->flags & FBINFO_HWACCEL_DISABLED) {
72 cfb_fillrect(info, region); 77 cfb_fillrect(info, region);
73 return; 78 return;
74 } 79 }
75 80
76 radeon_fixup_offset(rinfo);
77
78 vxres = info->var.xres_virtual; 81 vxres = info->var.xres_virtual;
79 vyres = info->var.yres_virtual; 82 vyres = info->var.yres_virtual;
80 83
@@ -87,6 +90,10 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
87 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 90 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
88 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 91 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
89 92
93 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
94 info->fix.visual == FB_VISUAL_DIRECTCOLOR )
95 modded.color = ((u32 *) (info->pseudo_palette))[region->color];
96
90 radeonfb_prim_fillrect(rinfo, &modded); 97 radeonfb_prim_fillrect(rinfo, &modded);
91} 98}
92 99
@@ -105,18 +112,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
105 if ( xdir < 0 ) { sx += w-1; dx += w-1; } 112 if ( xdir < 0 ) { sx += w-1; dx += w-1; }
106 if ( ydir < 0 ) { sy += h-1; dy += h-1; } 113 if ( ydir < 0 ) { sy += h-1; dy += h-1; }
107 114
108 radeon_fifo_wait(3); 115 radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
109 OUTREG(DP_GUI_MASTER_CNTL, 116 rinfo->dp_gui_mc_base |
110 rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ 117 GMC_BRUSH_NONE |
111 | GMC_BRUSH_NONE 118 GMC_SRC_DATATYPE_COLOR |
112 | GMC_SRC_DSTCOLOR 119 ROP3_S |
113 | ROP3_S 120 DP_SRC_SOURCE_MEMORY);
114 | DP_SRC_SOURCE_MEMORY ); 121 radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
115 OUTREG(DP_WRITE_MSK, 0xffffffff); 122 (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
116 OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) 123 (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
117 | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); 124
118 125#if FLUSH_CACHE_WORKAROUND
119 radeon_fifo_wait(3); 126 radeon_fifo_wait(rinfo, 2);
127 OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
128 OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
129#endif
130 radeon_fifo_wait(rinfo, 3);
120 OUTREG(SRC_Y_X, (sy << 16) | sx); 131 OUTREG(SRC_Y_X, (sy << 16) | sx);
121 OUTREG(DST_Y_X, (dy << 16) | dx); 132 OUTREG(DST_Y_X, (dy << 16) | dx);
122 OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); 133 OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
@@ -135,15 +146,14 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
135 modded.width = area->width; 146 modded.width = area->width;
136 modded.height = area->height; 147 modded.height = area->height;
137 148
138 if (info->state != FBINFO_STATE_RUNNING) 149 WARN_ON(rinfo->gfx_mode);
150 if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
139 return; 151 return;
140 if (info->flags & FBINFO_HWACCEL_DISABLED) { 152 if (info->flags & FBINFO_HWACCEL_DISABLED) {
141 cfb_copyarea(info, area); 153 cfb_copyarea(info, area);
142 return; 154 return;
143 } 155 }
144 156
145 radeon_fixup_offset(rinfo);
146
147 vxres = info->var.xres_virtual; 157 vxres = info->var.xres_virtual;
148 vyres = info->var.yres_virtual; 158 vyres = info->var.yres_virtual;
149 159
@@ -160,13 +170,112 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
160 radeonfb_prim_copyarea(rinfo, &modded); 170 radeonfb_prim_copyarea(rinfo, &modded);
161} 171}
162 172
173static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo,
174 const struct fb_image *image,
175 u32 fg, u32 bg)
176{
177 unsigned int src_bytes, dwords;
178 u32 *bits;
179
180 radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
181 rinfo->dp_gui_mc_base |
182 GMC_BRUSH_NONE |
183 GMC_SRC_DATATYPE_MONO_FG_BG |
184 ROP3_S |
185 GMC_BYTE_ORDER_MSB_TO_LSB |
186 DP_SRC_SOURCE_HOST_DATA);
187 radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
188 DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
189 radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg);
190 radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg);
191
192 radeon_fifo_wait(rinfo, 1);
193 OUTREG(DST_Y_X, (image->dy << 16) | image->dx);
194
195 /* Ensure the dst cache is flushed and the engine idle before
196 * issuing the operation.
197 *
198 * This works around engine lockups on some cards
199 */
200#if FLUSH_CACHE_WORKAROUND
201 radeon_fifo_wait(rinfo, 2);
202 OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
203 OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
204#endif
205
206 /* X here pads width to a multiple of 32 and uses the clipper to
207 * adjust the result. Is that really necessary ? Things seem to
208 * work ok for me without that and the doco doesn't seem to imply
209 * there is such a restriction.
210 */
211 OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height);
212
213 src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
214 dwords = (src_bytes + 3) / 4;
215 bits = (u32*)(image->data);
216
217 while(dwords >= 8) {
218 radeon_fifo_wait(rinfo, 8);
219#if BITS_PER_LONG == 64
220 __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0);
221 __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2);
222 __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4);
223 __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6);
224 bits += 8;
225#else
226 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
227 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1);
228 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2);
229 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3);
230 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4);
231 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5);
232 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6);
233 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7);
234#endif
235 dwords -= 8;
236 }
237 while(dwords--) {
238 radeon_fifo_wait(rinfo, 1);
239 __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
240 }
241}
242
163void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) 243void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
164{ 244{
165 struct radeonfb_info *rinfo = info->par; 245 struct radeonfb_info *rinfo = info->par;
246 u32 fg, bg;
166 247
167 if (info->state != FBINFO_STATE_RUNNING) 248 WARN_ON(rinfo->gfx_mode);
249 if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
168 return; 250 return;
169 radeon_engine_idle(); 251
252 if (!image->width || !image->height)
253 return;
254
255 /* We only do 1 bpp color expansion for now */
256 if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
257 goto fallback;
258
259 /* Fallback if running out of the screen. We may do clipping
260 * in the future */
261 if ((image->dx + image->width) > info->var.xres_virtual ||
262 (image->dy + image->height) > info->var.yres_virtual)
263 goto fallback;
264
265 if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
266 info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
267 fg = ((u32*)(info->pseudo_palette))[image->fg_color];
268 bg = ((u32*)(info->pseudo_palette))[image->bg_color];
269 } else {
270 fg = image->fg_color;
271 bg = image->bg_color;
272 }
273
274 radeonfb_prim_imageblit(rinfo, image, fg, bg);
275 return;
276
277 fallback:
278 radeon_engine_idle(rinfo);
170 279
171 cfb_imageblit(info, image); 280 cfb_imageblit(info, image);
172} 281}
@@ -177,7 +286,8 @@ int radeonfb_sync(struct fb_info *info)
177 286
178 if (info->state != FBINFO_STATE_RUNNING) 287 if (info->state != FBINFO_STATE_RUNNING)
179 return 0; 288 return 0;
180 radeon_engine_idle(); 289
290 radeon_engine_idle(rinfo);
181 291
182 return 0; 292 return 0;
183} 293}
@@ -203,9 +313,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
203 host_path_cntl = INREG(HOST_PATH_CNTL); 313 host_path_cntl = INREG(HOST_PATH_CNTL);
204 rbbm_soft_reset = INREG(RBBM_SOFT_RESET); 314 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
205 315
206 if (rinfo->family == CHIP_FAMILY_R300 || 316 if (IS_R300_VARIANT(rinfo)) {
207 rinfo->family == CHIP_FAMILY_R350 ||
208 rinfo->family == CHIP_FAMILY_RV350) {
209 u32 tmp; 317 u32 tmp;
210 318
211 OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | 319 OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
@@ -241,9 +349,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
241 INREG(HOST_PATH_CNTL); 349 INREG(HOST_PATH_CNTL);
242 OUTREG(HOST_PATH_CNTL, host_path_cntl); 350 OUTREG(HOST_PATH_CNTL, host_path_cntl);
243 351
244 if (rinfo->family != CHIP_FAMILY_R300 || 352 if (!IS_R300_VARIANT(rinfo))
245 rinfo->family != CHIP_FAMILY_R350 ||
246 rinfo->family != CHIP_FAMILY_RV350)
247 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); 353 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
248 354
249 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); 355 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
@@ -257,15 +363,24 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
257 /* disable 3D engine */ 363 /* disable 3D engine */
258 OUTREG(RB3D_CNTL, 0); 364 OUTREG(RB3D_CNTL, 0);
259 365
366 rinfo->fifo_free = 0;
260 radeonfb_engine_reset(rinfo); 367 radeonfb_engine_reset(rinfo);
261 368
262 radeon_fifo_wait (1); 369 radeon_fifo_wait(rinfo, 1);
263 if ((rinfo->family != CHIP_FAMILY_R300) && 370 if (IS_R300_VARIANT(rinfo)) {
264 (rinfo->family != CHIP_FAMILY_R350) && 371 OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
265 (rinfo->family != CHIP_FAMILY_RV350)) 372 RB2D_DC_AUTOFLUSH_ENABLE |
373 RB2D_DC_DC_DISABLE_IGNORE_PE);
374 } else {
375 /* This needs to be double checked with ATI. Latest X driver
376 * completely "forgets" to set this register on < r3xx, and
377 * we used to just write 0 there... I'll keep the 0 and update
378 * that when we have sorted things out on X side.
379 */
266 OUTREG(RB2D_DSTCACHE_MODE, 0); 380 OUTREG(RB2D_DSTCACHE_MODE, 0);
381 }
267 382
268 radeon_fifo_wait (3); 383 radeon_fifo_wait(rinfo, 3);
269 /* We re-read MC_FB_LOCATION from card as it can have been 384 /* We re-read MC_FB_LOCATION from card as it can have been
270 * modified by XFree drivers (ouch !) 385 * modified by XFree drivers (ouch !)
271 */ 386 */
@@ -276,41 +391,57 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
276 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 391 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
277 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 392 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
278 393
279 radeon_fifo_wait (1); 394 radeon_fifo_wait(rinfo, 1);
280#if defined(__BIG_ENDIAN) 395#ifdef __BIG_ENDIAN
281 OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); 396 OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
282#else 397#else
283 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); 398 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
284#endif 399#endif
285 radeon_fifo_wait (2); 400 radeon_fifo_wait(rinfo, 2);
286 OUTREG(DEFAULT_SC_TOP_LEFT, 0); 401 OUTREG(DEFAULT_SC_TOP_LEFT, 0);
287 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | 402 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
288 DEFAULT_SC_BOTTOM_MAX)); 403 DEFAULT_SC_BOTTOM_MAX));
289 404
405 /* set default DP_GUI_MASTER_CNTL */
290 temp = radeon_get_dstbpp(rinfo->depth); 406 temp = radeon_get_dstbpp(rinfo->depth);
291 rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); 407 rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
292 408
293 radeon_fifo_wait (1); 409 rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base |
294 OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | 410 GMC_BRUSH_SOLID_COLOR |
295 GMC_BRUSH_SOLID_COLOR | 411 GMC_SRC_DATATYPE_COLOR;
296 GMC_SRC_DATATYPE_COLOR)); 412 radeon_fifo_wait(rinfo, 1);
413 OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache);
297 414
298 radeon_fifo_wait (7);
299 415
300 /* clear line drawing regs */ 416 /* clear line drawing regs */
417 radeon_fifo_wait(rinfo, 2);
301 OUTREG(DST_LINE_START, 0); 418 OUTREG(DST_LINE_START, 0);
302 OUTREG(DST_LINE_END, 0); 419 OUTREG(DST_LINE_END, 0);
303 420
304 /* set brush color regs */ 421 /* set brush and source color regs */
305 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); 422 rinfo->dp_brush_fg_cache = 0xffffffff;
306 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); 423 rinfo->dp_brush_bg_cache = 0x00000000;
307 424 rinfo->dp_src_fg_cache = 0xffffffff;
308 /* set source color regs */ 425 rinfo->dp_src_bg_cache = 0x00000000;
309 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); 426 radeon_fifo_wait(rinfo, 4);
310 OUTREG(DP_SRC_BKGD_CLR, 0x00000000); 427 OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache);
428 OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache);
429 OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache);
430 OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache);
431
432 /* Default direction */
433 rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM;
434 radeon_fifo_wait(rinfo, 1);
435 OUTREG(DP_CNTL, rinfo->dp_cntl_cache);
311 436
312 /* default write mask */ 437 /* default write mask */
438 radeon_fifo_wait(rinfo, 1);
313 OUTREG(DP_WRITE_MSK, 0xffffffff); 439 OUTREG(DP_WRITE_MSK, 0xffffffff);
314 440
315 radeon_engine_idle (); 441 /* Default to no swapping of host data */
442 radeon_fifo_wait(rinfo, 1);
443 OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE);
444
445 /* Make sure it's settled */
446 radeon_engine_idle(rinfo);
316} 447}
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 1a056adb61c8..f343ba83f0ae 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
66 level = bd->props.brightness; 66 level = bd->props.brightness;
67 67
68 del_timer_sync(&rinfo->lvds_timer); 68 del_timer_sync(&rinfo->lvds_timer);
69 radeon_engine_idle(); 69 radeon_engine_idle(rinfo);
70 70
71 lvds_gen_cntl = INREG(LVDS_GEN_CNTL); 71 lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
72 if (level > 0) { 72 if (level > 0) {
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 400e9264e456..9a5821c65ebf 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -852,7 +852,6 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
852 if (rinfo->asleep) 852 if (rinfo->asleep)
853 return 0; 853 return 0;
854 854
855 radeon_fifo_wait(2);
856 OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) 855 OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
857 * var->bits_per_pixel / 8) & ~7); 856 * var->bits_per_pixel / 8) & ~7);
858 return 0; 857 return 0;
@@ -882,7 +881,6 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
882 if (rc) 881 if (rc)
883 return rc; 882 return rc;
884 883
885 radeon_fifo_wait(2);
886 if (value & 0x01) { 884 if (value & 0x01) {
887 tmp = INREG(LVDS_GEN_CNTL); 885 tmp = INREG(LVDS_GEN_CNTL);
888 886
@@ -940,7 +938,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
940 if (rinfo->lock_blank) 938 if (rinfo->lock_blank)
941 return 0; 939 return 0;
942 940
943 radeon_engine_idle(); 941 radeon_engine_idle(rinfo);
944 942
945 val = INREG(CRTC_EXT_CNTL); 943 val = INREG(CRTC_EXT_CNTL);
946 val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | 944 val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
@@ -1048,7 +1046,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
1048 1046
1049 if (rinfo->asleep) 1047 if (rinfo->asleep)
1050 return 0; 1048 return 0;
1051 1049
1052 return radeon_screen_blank(rinfo, blank, 0); 1050 return radeon_screen_blank(rinfo, blank, 0);
1053} 1051}
1054 1052
@@ -1074,8 +1072,6 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
1074 pindex = regno; 1072 pindex = regno;
1075 1073
1076 if (!rinfo->asleep) { 1074 if (!rinfo->asleep) {
1077 radeon_fifo_wait(9);
1078
1079 if (rinfo->bpp == 16) { 1075 if (rinfo->bpp == 16) {
1080 pindex = regno * 8; 1076 pindex = regno * 8;
1081 1077
@@ -1244,8 +1240,6 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
1244{ 1240{
1245 int i; 1241 int i;
1246 1242
1247 radeon_fifo_wait(20);
1248
1249 /* Workaround from XFree */ 1243 /* Workaround from XFree */
1250 if (rinfo->is_mobility) { 1244 if (rinfo->is_mobility) {
1251 /* A temporal workaround for the occational blanking on certain laptop 1245 /* A temporal workaround for the occational blanking on certain laptop
@@ -1286,11 +1280,10 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
1286 radeon_pll_errata_after_data(rinfo); 1280 radeon_pll_errata_after_data(rinfo);
1287 1281
1288 /* Set PPLL ref. div */ 1282 /* Set PPLL ref. div */
1289 if (rinfo->family == CHIP_FAMILY_R300 || 1283 if (IS_R300_VARIANT(rinfo) ||
1290 rinfo->family == CHIP_FAMILY_RS300 || 1284 rinfo->family == CHIP_FAMILY_RS300 ||
1291 rinfo->family == CHIP_FAMILY_R350 || 1285 rinfo->family == CHIP_FAMILY_RS400 ||
1292 rinfo->family == CHIP_FAMILY_RV350 || 1286 rinfo->family == CHIP_FAMILY_RS480) {
1293 rinfo->family == CHIP_FAMILY_RV380 ) {
1294 if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { 1287 if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
1295 /* When restoring console mode, use saved PPLL_REF_DIV 1288 /* When restoring console mode, use saved PPLL_REF_DIV
1296 * setting. 1289 * setting.
@@ -1342,7 +1335,7 @@ static void radeon_lvds_timer_func(unsigned long data)
1342{ 1335{
1343 struct radeonfb_info *rinfo = (struct radeonfb_info *)data; 1336 struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
1344 1337
1345 radeon_engine_idle(); 1338 radeon_engine_idle(rinfo);
1346 1339
1347 OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); 1340 OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
1348} 1341}
@@ -1360,10 +1353,11 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
1360 if (nomodeset) 1353 if (nomodeset)
1361 return; 1354 return;
1362 1355
1356 radeon_engine_idle(rinfo);
1357
1363 if (!regs_only) 1358 if (!regs_only)
1364 radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); 1359 radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
1365 1360
1366 radeon_fifo_wait(31);
1367 for (i=0; i<10; i++) 1361 for (i=0; i<10; i++)
1368 OUTREG(common_regs[i].reg, common_regs[i].val); 1362 OUTREG(common_regs[i].reg, common_regs[i].val);
1369 1363
@@ -1391,7 +1385,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
1391 radeon_write_pll_regs(rinfo, mode); 1385 radeon_write_pll_regs(rinfo, mode);
1392 1386
1393 if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { 1387 if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
1394 radeon_fifo_wait(10);
1395 OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); 1388 OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
1396 OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); 1389 OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
1397 OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); 1390 OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
@@ -1406,7 +1399,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
1406 if (!regs_only) 1399 if (!regs_only)
1407 radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); 1400 radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
1408 1401
1409 radeon_fifo_wait(2);
1410 OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); 1402 OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
1411 1403
1412 return; 1404 return;
@@ -1461,10 +1453,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
1461 /* Not all chip revs have the same format for this register, 1453 /* Not all chip revs have the same format for this register,
1462 * extract the source selection 1454 * extract the source selection
1463 */ 1455 */
1464 if (rinfo->family == CHIP_FAMILY_R200 || 1456 if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
1465 rinfo->family == CHIP_FAMILY_R300 ||
1466 rinfo->family == CHIP_FAMILY_R350 ||
1467 rinfo->family == CHIP_FAMILY_RV350) {
1468 source = (fp2_gen_cntl >> 10) & 0x3; 1457 source = (fp2_gen_cntl >> 10) & 0x3;
1469 /* sourced from transform unit, check for transform unit 1458 /* sourced from transform unit, check for transform unit
1470 * own source 1459 * own source
@@ -1560,7 +1549,7 @@ static int radeonfb_set_par(struct fb_info *info)
1560 /* We always want engine to be idle on a mode switch, even 1549 /* We always want engine to be idle on a mode switch, even
1561 * if we won't actually change the mode 1550 * if we won't actually change the mode
1562 */ 1551 */
1563 radeon_engine_idle(); 1552 radeon_engine_idle(rinfo);
1564 1553
1565 hSyncStart = mode->xres + mode->right_margin; 1554 hSyncStart = mode->xres + mode->right_margin;
1566 hSyncEnd = hSyncStart + mode->hsync_len; 1555 hSyncEnd = hSyncStart + mode->hsync_len;
@@ -1855,7 +1844,6 @@ static int radeonfb_set_par(struct fb_info *info)
1855 return 0; 1844 return 0;
1856} 1845}
1857 1846
1858
1859static struct fb_ops radeonfb_ops = { 1847static struct fb_ops radeonfb_ops = {
1860 .owner = THIS_MODULE, 1848 .owner = THIS_MODULE,
1861 .fb_check_var = radeonfb_check_var, 1849 .fb_check_var = radeonfb_check_var,
@@ -1879,6 +1867,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
1879 info->par = rinfo; 1867 info->par = rinfo;
1880 info->pseudo_palette = rinfo->pseudo_palette; 1868 info->pseudo_palette = rinfo->pseudo_palette;
1881 info->flags = FBINFO_DEFAULT 1869 info->flags = FBINFO_DEFAULT
1870 | FBINFO_HWACCEL_IMAGEBLIT
1882 | FBINFO_HWACCEL_COPYAREA 1871 | FBINFO_HWACCEL_COPYAREA
1883 | FBINFO_HWACCEL_FILLRECT 1872 | FBINFO_HWACCEL_FILLRECT
1884 | FBINFO_HWACCEL_XPAN 1873 | FBINFO_HWACCEL_XPAN
@@ -2005,11 +1994,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
2005 (rinfo->family == CHIP_FAMILY_RS200) || 1994 (rinfo->family == CHIP_FAMILY_RS200) ||
2006 (rinfo->family == CHIP_FAMILY_RS300) || 1995 (rinfo->family == CHIP_FAMILY_RS300) ||
2007 (rinfo->family == CHIP_FAMILY_RC410) || 1996 (rinfo->family == CHIP_FAMILY_RC410) ||
1997 (rinfo->family == CHIP_FAMILY_RS400) ||
2008 (rinfo->family == CHIP_FAMILY_RS480) ) { 1998 (rinfo->family == CHIP_FAMILY_RS480) ) {
2009 u32 tom = INREG(NB_TOM); 1999 u32 tom = INREG(NB_TOM);
2010 tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); 2000 tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
2011 2001
2012 radeon_fifo_wait(6);
2013 OUTREG(MC_FB_LOCATION, tom); 2002 OUTREG(MC_FB_LOCATION, tom);
2014 OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); 2003 OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
2015 OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); 2004 OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
@@ -2098,15 +2087,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
2098 2087
2099static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid) 2088static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid)
2100{ 2089{
2101 if (off > EDID_LENGTH) 2090 return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH);
2102 return 0;
2103
2104 if (off + count > EDID_LENGTH)
2105 count = EDID_LENGTH - off;
2106
2107 memcpy(buf, edid + off, count);
2108
2109 return count;
2110} 2091}
2111 2092
2112 2093
@@ -2161,6 +2142,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
2161 struct radeonfb_info *rinfo; 2142 struct radeonfb_info *rinfo;
2162 int ret; 2143 int ret;
2163 unsigned char c1, c2; 2144 unsigned char c1, c2;
2145 int err = 0;
2164 2146
2165 pr_debug("radeonfb_pci_register BEGIN\n"); 2147 pr_debug("radeonfb_pci_register BEGIN\n");
2166 2148
@@ -2340,9 +2322,14 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
2340 2322
2341 /* Register some sysfs stuff (should be done better) */ 2323 /* Register some sysfs stuff (should be done better) */
2342 if (rinfo->mon1_EDID) 2324 if (rinfo->mon1_EDID)
2343 sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr); 2325 err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
2326 &edid1_attr);
2344 if (rinfo->mon2_EDID) 2327 if (rinfo->mon2_EDID)
2345 sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr); 2328 err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
2329 &edid2_attr);
2330 if (err)
2331 pr_warning("%s() Creating sysfs files failed, continuing\n",
2332 __func__);
2346 2333
2347 /* save current mode regs before we switch into the new one 2334 /* save current mode regs before we switch into the new one
2348 * so we can restore this upon __exit 2335 * so we can restore this upon __exit
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index f9e7c29ad9bf..2c5567175dca 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -69,7 +69,8 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
69{ 69{
70 int rc; 70 int rc;
71 71
72 strcpy(chan->adapter.name, name); 72 snprintf(chan->adapter.name, sizeof(chan->adapter.name),
73 "radeonfb %s", name);
73 chan->adapter.owner = THIS_MODULE; 74 chan->adapter.owner = THIS_MODULE;
74 chan->adapter.id = I2C_HW_B_RADEON; 75 chan->adapter.id = I2C_HW_B_RADEON;
75 chan->adapter.algo_data = &chan->algo; 76 chan->adapter.algo_data = &chan->algo;
@@ -138,12 +139,8 @@ void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
138int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, 139int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
139 u8 **out_edid) 140 u8 **out_edid)
140{ 141{
141 u32 reg = rinfo->i2c[conn-1].ddc_reg;
142 u8 *edid; 142 u8 *edid;
143 143
144 OUTREG(reg, INREG(reg) &
145 ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT));
146
147 edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter); 144 edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
148 145
149 if (out_edid) 146 if (out_edid)
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 675abdafc2d8..3df5015f1d13 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
2653 2653
2654 if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { 2654 if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
2655 /* Make sure engine is reset */ 2655 /* Make sure engine is reset */
2656 radeon_engine_idle(); 2656 radeon_engine_idle(rinfo);
2657 radeonfb_engine_reset(rinfo); 2657 radeonfb_engine_reset(rinfo);
2658 radeon_engine_idle(); 2658 radeon_engine_idle(rinfo);
2659 } 2659 }
2660 2660
2661 /* Blank display and LCD */ 2661 /* Blank display and LCD */
@@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
2767 2767
2768 rinfo->asleep = 0; 2768 rinfo->asleep = 0;
2769 } else 2769 } else
2770 radeon_engine_idle(); 2770 radeon_engine_idle(rinfo);
2771 2771
2772 /* Restore display & engine */ 2772 /* Restore display & engine */
2773 radeon_write_mode (rinfo, &rinfo->state, 1); 2773 radeon_write_mode (rinfo, &rinfo->state, 1);
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index c347e38cd0b0..ea0b5b47acaf 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -53,6 +53,7 @@ enum radeon_family {
53 CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ 53 CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
54 CHIP_FAMILY_R420, /* R420/R423/M18 */ 54 CHIP_FAMILY_R420, /* R420/R423/M18 */
55 CHIP_FAMILY_RC410, 55 CHIP_FAMILY_RC410,
56 CHIP_FAMILY_RS400,
56 CHIP_FAMILY_RS480, 57 CHIP_FAMILY_RS480,
57 CHIP_FAMILY_LAST, 58 CHIP_FAMILY_LAST,
58}; 59};
@@ -289,7 +290,7 @@ struct radeonfb_info {
289 struct radeon_regs state; 290 struct radeon_regs state;
290 struct radeon_regs init_state; 291 struct radeon_regs init_state;
291 292
292 char name[DEVICE_NAME_SIZE]; 293 char name[50];
293 294
294 unsigned long mmio_base_phys; 295 unsigned long mmio_base_phys;
295 unsigned long fb_base_phys; 296 unsigned long fb_base_phys;
@@ -335,7 +336,15 @@ struct radeonfb_info {
335 int mon2_type; 336 int mon2_type;
336 u8 *mon2_EDID; 337 u8 *mon2_EDID;
337 338
338 u32 dp_gui_master_cntl; 339 /* accel bits */
340 u32 dp_gui_mc_base;
341 u32 dp_gui_mc_cache;
342 u32 dp_cntl_cache;
343 u32 dp_brush_fg_cache;
344 u32 dp_brush_bg_cache;
345 u32 dp_src_fg_cache;
346 u32 dp_src_bg_cache;
347 u32 fifo_free;
339 348
340 struct pll_info pll; 349 struct pll_info pll;
341 350
@@ -347,6 +356,7 @@ struct radeonfb_info {
347 int lock_blank; 356 int lock_blank;
348 int dynclk; 357 int dynclk;
349 int no_schedule; 358 int no_schedule;
359 int gfx_mode;
350 enum radeon_pm_mode pm_mode; 360 enum radeon_pm_mode pm_mode;
351 reinit_function_ptr reinit_func; 361 reinit_function_ptr reinit_func;
352 362
@@ -391,8 +401,14 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
391#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) 401#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
392#define INREG16(addr) readw((rinfo->mmio_base)+addr) 402#define INREG16(addr) readw((rinfo->mmio_base)+addr)
393#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) 403#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
404
405#ifdef CONFIG_PPC
406#define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); })
407#define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0)
408#else
394#define INREG(addr) readl((rinfo->mmio_base)+addr) 409#define INREG(addr) readl((rinfo->mmio_base)+addr)
395#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) 410#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
411#endif
396 412
397static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, 413static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
398 u32 val, u32 mask) 414 u32 val, u32 mask)
@@ -533,16 +549,25 @@ static inline u32 radeon_get_dstbpp(u16 depth)
533/* 549/*
534 * 2D Engine helper routines 550 * 2D Engine helper routines
535 */ 551 */
552
553extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries);
554
536static inline void radeon_engine_flush (struct radeonfb_info *rinfo) 555static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
537{ 556{
538 int i; 557 int i;
539 558
540 /* initiate flush */ 559 /* Initiate flush */
541 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, 560 OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
542 ~RB2D_DC_FLUSH_ALL); 561 ~RB2D_DC_FLUSH_ALL);
543 562
563 /* Ensure FIFO is empty, ie, make sure the flush commands
564 * has reached the cache
565 */
566 radeon_fifo_update_and_wait(rinfo, 64);
567
568 /* Wait for the flush to complete */
544 for (i=0; i < 2000000; i++) { 569 for (i=0; i < 2000000; i++) {
545 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) 570 if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
546 return; 571 return;
547 udelay(1); 572 udelay(1);
548 } 573 }
@@ -550,25 +575,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
550} 575}
551 576
552 577
553static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) 578static inline void radeon_engine_idle(struct radeonfb_info *rinfo)
554{
555 int i;
556
557 for (i=0; i<2000000; i++) {
558 if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
559 return;
560 udelay(1);
561 }
562 printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
563}
564
565
566static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
567{ 579{
568 int i; 580 int i;
569 581
570 /* ensure FIFO is empty before waiting for idle */ 582 /* ensure FIFO is empty before waiting for idle */
571 _radeon_fifo_wait (rinfo, 64); 583 radeon_fifo_update_and_wait (rinfo, 64);
572 584
573 for (i=0; i<2000000; i++) { 585 for (i=0; i<2000000; i++) {
574 if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { 586 if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
@@ -581,8 +593,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
581} 593}
582 594
583 595
584#define radeon_engine_idle() _radeon_engine_idle(rinfo)
585#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
586#define radeon_msleep(ms) _radeon_msleep(rinfo,ms) 596#define radeon_msleep(ms) _radeon_msleep(rinfo,ms)
587 597
588 598
@@ -612,6 +622,7 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
612extern int radeonfb_sync(struct fb_info *info); 622extern int radeonfb_sync(struct fb_info *info);
613extern void radeonfb_engine_init (struct radeonfb_info *rinfo); 623extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
614extern void radeonfb_engine_reset(struct radeonfb_info *rinfo); 624extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
625extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo);
615 626
616/* Other functions */ 627/* Other functions */
617extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch); 628extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 30bf7f2f1635..4a4dd9adc328 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -24,6 +24,13 @@ config LCD_CLASS_DEVICE
24 To have support for your specific LCD panel you will have to 24 To have support for your specific LCD panel you will have to
25 select the proper drivers which depend on this option. 25 select the proper drivers which depend on this option.
26 26
27config LCD_CORGI
28 tristate "LCD Panel support for SHARP corgi/spitz model"
29 depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL
30 help
31 Say y here to support the LCD panels usually found on SHARP
32 corgi (C7x0) and spitz (Cxx00) models.
33
27config LCD_LTV350QV 34config LCD_LTV350QV
28 tristate "Samsung LTV350QV LCD Panel" 35 tristate "Samsung LTV350QV LCD Panel"
29 depends on LCD_CLASS_DEVICE && SPI_MASTER 36 depends on LCD_CLASS_DEVICE && SPI_MASTER
@@ -36,6 +43,47 @@ config LCD_LTV350QV
36 43
37 The LTV350QV panel is present on all ATSTK1000 boards. 44 The LTV350QV panel is present on all ATSTK1000 boards.
38 45
46config LCD_ILI9320
47 tristate
48 depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
49 default n
50 help
51 If you have a panel based on the ILI9320 controller chip
52 then say y to include a power driver for it.
53
54config LCD_TDO24M
55 tristate "Toppoly TDO24M LCD Panels support"
56 depends on LCD_CLASS_DEVICE && SPI_MASTER
57 default n
58 help
59 If you have a Toppoly TDO24M series LCD panel, say y here to
60 include the support for it.
61
62config LCD_VGG2432A4
63 tristate "VGG2432A4 LCM device support"
64 depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
65 select LCD_ILI9320
66 default n
67 help
68 If you have a VGG2432A4 panel based on the ILI9320 controller chip
69 then say y to include a power driver for it.
70
71config LCD_PLATFORM
72 tristate "Platform LCD controls"
73 depends on LCD_CLASS_DEVICE
74 help
75 This driver provides a platform-device registered LCD power
76 control interface.
77
78config LCD_TOSA
79 tristate "Sharp SL-6000 LCD Driver"
80 depends on LCD_CLASS_DEVICE && SPI
81 depends on MACH_TOSA
82 default n
83 help
84 If you have an Sharp SL-6000 Zaurus say Y to enable a driver
85 for its LCD.
86
39# 87#
40# Backlight 88# Backlight
41# 89#
@@ -63,8 +111,20 @@ config BACKLIGHT_ATMEL_LCDC
63 If in doubt, it's safe to enable this option; it doesn't kick 111 If in doubt, it's safe to enable this option; it doesn't kick
64 in unless the board's description says it's wired that way. 112 in unless the board's description says it's wired that way.
65 113
114config BACKLIGHT_ATMEL_PWM
115 tristate "Atmel PWM backlight control"
116 depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM
117 default n
118 help
119 Say Y here if you want to use the PWM peripheral in Atmel AT91 and
120 AVR32 devices. This driver will need additional platform data to know
121 which PWM instance to use and how to configure it.
122
123 To compile this driver as a module, choose M here: the module will be
124 called atmel-pwm-bl.
125
66config BACKLIGHT_CORGI 126config BACKLIGHT_CORGI
67 tristate "Generic (aka Sharp Corgi) Backlight Driver" 127 tristate "Generic (aka Sharp Corgi) Backlight Driver (DEPRECATED)"
68 depends on BACKLIGHT_CLASS_DEVICE 128 depends on BACKLIGHT_CLASS_DEVICE
69 default n 129 default n
70 help 130 help
@@ -72,6 +132,9 @@ config BACKLIGHT_CORGI
72 known as the Corgi backlight driver. If you have a Sharp Zaurus 132 known as the Corgi backlight driver. If you have a Sharp Zaurus
73 SL-C7xx, SL-Cxx00 or SL-6000x say y. Most users can say n. 133 SL-C7xx, SL-Cxx00 or SL-6000x say y. Most users can say n.
74 134
135 Note: this driver is marked as deprecated, try enable SPI and
136 use the new corgi_lcd driver with integrated backlight control
137
75config BACKLIGHT_LOCOMO 138config BACKLIGHT_LOCOMO
76 tristate "Sharp LOCOMO LCD/Backlight Driver" 139 tristate "Sharp LOCOMO LCD/Backlight Driver"
77 depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO 140 depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
@@ -119,3 +182,35 @@ config BACKLIGHT_PWM
119 help 182 help
120 If you have a LCD backlight adjustable by PWM, say Y to enable 183 If you have a LCD backlight adjustable by PWM, say Y to enable
121 this driver. 184 this driver.
185
186config BACKLIGHT_DA903X
187 tristate "Backlight Driver for DA9030/DA9034 using WLED"
188 depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X
189 help
190 If you have a LCD backlight connected to the WLED output of DA9030
191 or DA9034 WLED output, say Y here to enable this driver.
192
193config BACKLIGHT_MBP_NVIDIA
194 tristate "MacBook Pro Nvidia Backlight Driver"
195 depends on BACKLIGHT_CLASS_DEVICE && X86
196 default n
197 help
198 If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
199 to enable a driver for its backlight
200
201config BACKLIGHT_TOSA
202 tristate "Sharp SL-6000 Backlight Driver"
203 depends on BACKLIGHT_CLASS_DEVICE && I2C
204 depends on MACH_TOSA && LCD_TOSA
205 default n
206 help
207 If you have an Sharp SL-6000 Zaurus say Y to enable a driver
208 for its backlight
209
210config BACKLIGHT_SAHARA
211 tristate "Tabletkiosk Sahara Touch-iT Backlight Driver"
212 depends on BACKLIGHT_CLASS_DEVICE && X86
213 default n
214 help
215 If you have a Tabletkiosk Sahara Touch-iT, say y to enable the
216 backlight driver.
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index b51a7cd12500..103427de6703 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -1,9 +1,16 @@
1# Backlight & LCD drivers 1# Backlight & LCD drivers
2 2
3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o 3obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
4obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o 4obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
5obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
6obj-$(CONFIG_LCD_ILI9320) += ili9320.o
7obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
8obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
9obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
10obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
5 11
6obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 12obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
13obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
7obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o 14obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
8obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o 15obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
9obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o 16obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
@@ -11,3 +18,8 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
11obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o 18obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
12obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o 19obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
13obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o 20obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
21obj-$(CONFIG_BACKLIGHT_DA903X) += da903x.o
22obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
23obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
24obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
25
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
new file mode 100644
index 000000000000..505c0823a105
--- /dev/null
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -0,0 +1,244 @@
1/*
2 * Copyright (C) 2008 Atmel Corporation
3 *
4 * Backlight driver using Atmel PWM peripheral.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10#include <linux/init.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/fb.h>
15#include <linux/clk.h>
16#include <linux/gpio.h>
17#include <linux/backlight.h>
18#include <linux/atmel_pwm.h>
19#include <linux/atmel-pwm-bl.h>
20
21struct atmel_pwm_bl {
22 const struct atmel_pwm_bl_platform_data *pdata;
23 struct backlight_device *bldev;
24 struct platform_device *pdev;
25 struct pwm_channel pwmc;
26 int gpio_on;
27};
28
29static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
30{
31 struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
32 int intensity = bd->props.brightness;
33 int pwm_duty;
34
35 if (bd->props.power != FB_BLANK_UNBLANK)
36 intensity = 0;
37 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
38 intensity = 0;
39
40 if (pwmbl->pdata->pwm_active_low)
41 pwm_duty = pwmbl->pdata->pwm_duty_min + intensity;
42 else
43 pwm_duty = pwmbl->pdata->pwm_duty_max - intensity;
44
45 if (pwm_duty > pwmbl->pdata->pwm_duty_max)
46 pwm_duty = pwmbl->pdata->pwm_duty_max;
47 if (pwm_duty < pwmbl->pdata->pwm_duty_min)
48 pwm_duty = pwmbl->pdata->pwm_duty_min;
49
50 if (!intensity) {
51 if (pwmbl->gpio_on != -1) {
52 gpio_set_value(pwmbl->gpio_on,
53 0 ^ pwmbl->pdata->on_active_low);
54 }
55 pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
56 pwm_channel_disable(&pwmbl->pwmc);
57 } else {
58 pwm_channel_enable(&pwmbl->pwmc);
59 pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
60 if (pwmbl->gpio_on != -1) {
61 gpio_set_value(pwmbl->gpio_on,
62 1 ^ pwmbl->pdata->on_active_low);
63 }
64 }
65
66 return 0;
67}
68
69static int atmel_pwm_bl_get_intensity(struct backlight_device *bd)
70{
71 struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
72 u8 intensity;
73
74 if (pwmbl->pdata->pwm_active_low) {
75 intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) -
76 pwmbl->pdata->pwm_duty_min;
77 } else {
78 intensity = pwmbl->pdata->pwm_duty_max -
79 pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
80 }
81
82 return intensity;
83}
84
85static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
86{
87 unsigned long pwm_rate = pwmbl->pwmc.mck;
88 unsigned long prescale = DIV_ROUND_UP(pwm_rate,
89 (pwmbl->pdata->pwm_frequency *
90 pwmbl->pdata->pwm_compare_max)) - 1;
91
92 /*
93 * Prescale must be power of two and maximum 0xf in size because of
94 * hardware limit. PWM speed will be:
95 * PWM module clock speed / (2 ^ prescale).
96 */
97 prescale = fls(prescale);
98 if (prescale > 0xf)
99 prescale = 0xf;
100
101 pwm_channel_writel(&pwmbl->pwmc, PWM_CMR, prescale);
102 pwm_channel_writel(&pwmbl->pwmc, PWM_CDTY,
103 pwmbl->pdata->pwm_duty_min +
104 pwmbl->bldev->props.brightness);
105 pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
106 pwmbl->pdata->pwm_compare_max);
107
108 dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
109 "(%lu Hz)\n", pwmbl->pwmc.mck /
110 pwmbl->pdata->pwm_compare_max /
111 (1 << prescale));
112
113 return pwm_channel_enable(&pwmbl->pwmc);
114}
115
116static struct backlight_ops atmel_pwm_bl_ops = {
117 .get_brightness = atmel_pwm_bl_get_intensity,
118 .update_status = atmel_pwm_bl_set_intensity,
119};
120
121static int atmel_pwm_bl_probe(struct platform_device *pdev)
122{
123 const struct atmel_pwm_bl_platform_data *pdata;
124 struct backlight_device *bldev;
125 struct atmel_pwm_bl *pwmbl;
126 int retval;
127
128 pwmbl = kzalloc(sizeof(struct atmel_pwm_bl), GFP_KERNEL);
129 if (!pwmbl)
130 return -ENOMEM;
131
132 pwmbl->pdev = pdev;
133
134 pdata = pdev->dev.platform_data;
135 if (!pdata) {
136 retval = -ENODEV;
137 goto err_free_mem;
138 }
139
140 if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
141 pdata->pwm_duty_min > pdata->pwm_duty_max ||
142 pdata->pwm_frequency == 0) {
143 retval = -EINVAL;
144 goto err_free_mem;
145 }
146
147 pwmbl->pdata = pdata;
148 pwmbl->gpio_on = pdata->gpio_on;
149
150 retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc);
151 if (retval)
152 goto err_free_mem;
153
154 if (pwmbl->gpio_on != -1) {
155 retval = gpio_request(pwmbl->gpio_on, "gpio_atmel_pwm_bl");
156 if (retval) {
157 pwmbl->gpio_on = -1;
158 goto err_free_pwm;
159 }
160
161 /* Turn display off by defatult. */
162 retval = gpio_direction_output(pwmbl->gpio_on,
163 0 ^ pdata->on_active_low);
164 if (retval)
165 goto err_free_gpio;
166 }
167
168 bldev = backlight_device_register("atmel-pwm-bl",
169 &pdev->dev, pwmbl, &atmel_pwm_bl_ops);
170 if (IS_ERR(bldev)) {
171 retval = PTR_ERR(bldev);
172 goto err_free_gpio;
173 }
174
175 pwmbl->bldev = bldev;
176
177 platform_set_drvdata(pdev, pwmbl);
178
179 /* Power up the backlight by default at middle intesity. */
180 bldev->props.power = FB_BLANK_UNBLANK;
181 bldev->props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
182 bldev->props.brightness = bldev->props.max_brightness / 2;
183
184 retval = atmel_pwm_bl_init_pwm(pwmbl);
185 if (retval)
186 goto err_free_bl_dev;
187
188 atmel_pwm_bl_set_intensity(bldev);
189
190 return 0;
191
192err_free_bl_dev:
193 platform_set_drvdata(pdev, NULL);
194 backlight_device_unregister(bldev);
195err_free_gpio:
196 if (pwmbl->gpio_on != -1)
197 gpio_free(pwmbl->gpio_on);
198err_free_pwm:
199 pwm_channel_free(&pwmbl->pwmc);
200err_free_mem:
201 kfree(pwmbl);
202 return retval;
203}
204
205static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
206{
207 struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
208
209 if (pwmbl->gpio_on != -1) {
210 gpio_set_value(pwmbl->gpio_on, 0);
211 gpio_free(pwmbl->gpio_on);
212 }
213 pwm_channel_disable(&pwmbl->pwmc);
214 pwm_channel_free(&pwmbl->pwmc);
215 backlight_device_unregister(pwmbl->bldev);
216 platform_set_drvdata(pdev, NULL);
217 kfree(pwmbl);
218
219 return 0;
220}
221
222static struct platform_driver atmel_pwm_bl_driver = {
223 .driver = {
224 .name = "atmel-pwm-bl",
225 },
226 /* REVISIT add suspend() and resume() */
227 .remove = __exit_p(atmel_pwm_bl_remove),
228};
229
230static int __init atmel_pwm_bl_init(void)
231{
232 return platform_driver_probe(&atmel_pwm_bl_driver, atmel_pwm_bl_probe);
233}
234module_init(atmel_pwm_bl_init);
235
236static void __exit atmel_pwm_bl_exit(void)
237{
238 platform_driver_unregister(&atmel_pwm_bl_driver);
239}
240module_exit(atmel_pwm_bl_exit);
241
242MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
243MODULE_DESCRIPTION("Atmel PWM backlight driver");
244MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 39394757679c..fab0bc874b58 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -191,6 +191,7 @@ static struct device_attribute bl_device_attributes[] = {
191 * backlight_device class. 191 * backlight_device class.
192 * @name: the name of the new object(must be the same as the name of the 192 * @name: the name of the new object(must be the same as the name of the
193 * respective framebuffer device). 193 * respective framebuffer device).
194 * @parent: a pointer to the parent device
194 * @devdata: an optional pointer to be stored for private driver use. The 195 * @devdata: an optional pointer to be stored for private driver use. The
195 * methods may retrieve it by using bl_get_data(bd). 196 * methods may retrieve it by using bl_get_data(bd).
196 * @ops: the backlight operations structure. 197 * @ops: the backlight operations structure.
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
new file mode 100644
index 000000000000..2afd47eefe74
--- /dev/null
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -0,0 +1,641 @@
1/*
2 * LCD/Backlight Driver for Sharp Zaurus Handhelds (various models)
3 *
4 * Copyright (c) 2004-2006 Richard Purdie
5 *
6 * Based on Sharp's 2.4 Backlight Driver
7 *
8 * Copyright (c) 2008 Marvell International Ltd.
9 * Converted to SPI device based LCD/Backlight device driver
10 * by Eric Miao <eric.miao@marvell.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/delay.h>
22#include <linux/gpio.h>
23#include <linux/fb.h>
24#include <linux/lcd.h>
25#include <linux/spi/spi.h>
26#include <linux/spi/corgi_lcd.h>
27#include <asm/mach/sharpsl_param.h>
28
29#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
30
31/* Register Addresses */
32#define RESCTL_ADRS 0x00
33#define PHACTRL_ADRS 0x01
34#define DUTYCTRL_ADRS 0x02
35#define POWERREG0_ADRS 0x03
36#define POWERREG1_ADRS 0x04
37#define GPOR3_ADRS 0x05
38#define PICTRL_ADRS 0x06
39#define POLCTRL_ADRS 0x07
40
41/* Register Bit Definitions */
42#define RESCTL_QVGA 0x01
43#define RESCTL_VGA 0x00
44
45#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
46#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
47#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
48
49#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
50#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
51#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
52
53#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
54#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
55#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
56#define POWER0_COM_ON 0x08 /* COM Power Supply ON */
57#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
58
59#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
60#define POWER0_COM_OFF 0x00 /* COM Power Supply OFF */
61#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
62
63#define PICTRL_INIT_STATE 0x01
64#define PICTRL_INIOFF 0x02
65#define PICTRL_POWER_DOWN 0x04
66#define PICTRL_COM_SIGNAL_OFF 0x08
67#define PICTRL_DAC_SIGNAL_OFF 0x10
68
69#define POLCTRL_SYNC_POL_FALL 0x01
70#define POLCTRL_EN_POL_FALL 0x02
71#define POLCTRL_DATA_POL_FALL 0x04
72#define POLCTRL_SYNC_ACT_H 0x08
73#define POLCTRL_EN_ACT_L 0x10
74
75#define POLCTRL_SYNC_POL_RISE 0x00
76#define POLCTRL_EN_POL_RISE 0x00
77#define POLCTRL_DATA_POL_RISE 0x00
78#define POLCTRL_SYNC_ACT_L 0x00
79#define POLCTRL_EN_ACT_H 0x00
80
81#define PHACTRL_PHASE_MANUAL 0x01
82#define DEFAULT_PHAD_QVGA (9)
83#define DEFAULT_COMADJ (125)
84
85struct corgi_lcd {
86 struct spi_device *spi_dev;
87 struct lcd_device *lcd_dev;
88 struct backlight_device *bl_dev;
89
90 int limit_mask;
91 int intensity;
92 int power;
93 int mode;
94 char buf[2];
95
96 int gpio_backlight_on;
97 int gpio_backlight_cont;
98 int gpio_backlight_cont_inverted;
99
100 void (*kick_battery)(void);
101};
102
103static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int reg, uint8_t val);
104
105static struct corgi_lcd *the_corgi_lcd;
106static unsigned long corgibl_flags;
107#define CORGIBL_SUSPENDED 0x01
108#define CORGIBL_BATTLOW 0x02
109
110/*
111 * This is only a psuedo I2C interface. We can't use the standard kernel
112 * routines as the interface is write only. We just assume the data is acked...
113 */
114static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data)
115{
116 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, data);
117 udelay(10);
118}
119
120static void lcdtg_i2c_send_bit(struct corgi_lcd *lcd, uint8_t data)
121{
122 lcdtg_ssp_i2c_send(lcd, data);
123 lcdtg_ssp_i2c_send(lcd, data | POWER0_COM_DCLK);
124 lcdtg_ssp_i2c_send(lcd, data);
125}
126
127static void lcdtg_i2c_send_start(struct corgi_lcd *lcd, uint8_t base)
128{
129 lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT);
130 lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK);
131 lcdtg_ssp_i2c_send(lcd, base);
132}
133
134static void lcdtg_i2c_send_stop(struct corgi_lcd *lcd, uint8_t base)
135{
136 lcdtg_ssp_i2c_send(lcd, base);
137 lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK);
138 lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT);
139}
140
141static void lcdtg_i2c_send_byte(struct corgi_lcd *lcd,
142 uint8_t base, uint8_t data)
143{
144 int i;
145 for (i = 0; i < 8; i++) {
146 if (data & 0x80)
147 lcdtg_i2c_send_bit(lcd, base | POWER0_COM_DOUT);
148 else
149 lcdtg_i2c_send_bit(lcd, base);
150 data <<= 1;
151 }
152}
153
154static void lcdtg_i2c_wait_ack(struct corgi_lcd *lcd, uint8_t base)
155{
156 lcdtg_i2c_send_bit(lcd, base);
157}
158
159static void lcdtg_set_common_voltage(struct corgi_lcd *lcd,
160 uint8_t base_data, uint8_t data)
161{
162 /* Set Common Voltage to M62332FP via I2C */
163 lcdtg_i2c_send_start(lcd, base_data);
164 lcdtg_i2c_send_byte(lcd, base_data, 0x9c);
165 lcdtg_i2c_wait_ack(lcd, base_data);
166 lcdtg_i2c_send_byte(lcd, base_data, 0x00);
167 lcdtg_i2c_wait_ack(lcd, base_data);
168 lcdtg_i2c_send_byte(lcd, base_data, data);
169 lcdtg_i2c_wait_ack(lcd, base_data);
170 lcdtg_i2c_send_stop(lcd, base_data);
171}
172
173static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int adrs, uint8_t data)
174{
175 struct spi_message msg;
176 struct spi_transfer xfer = {
177 .len = 1,
178 .cs_change = 1,
179 .tx_buf = lcd->buf,
180 };
181
182 lcd->buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f);
183 spi_message_init(&msg);
184 spi_message_add_tail(&xfer, &msg);
185
186 return spi_sync(lcd->spi_dev, &msg);
187}
188
189/* Set Phase Adjust */
190static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode)
191{
192 int adj;
193
194 switch(mode) {
195 case CORGI_LCD_MODE_VGA:
196 /* Setting for VGA */
197 adj = sharpsl_param.phadadj;
198 adj = (adj < 0) ? PHACTRL_PHASE_MANUAL :
199 PHACTRL_PHASE_MANUAL | ((adj & 0xf) << 1);
200 break;
201 case CORGI_LCD_MODE_QVGA:
202 default:
203 /* Setting for QVGA */
204 adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
205 break;
206 }
207
208 corgi_ssp_lcdtg_send(lcd, PHACTRL_ADRS, adj);
209}
210
211static void corgi_lcd_power_on(struct corgi_lcd *lcd)
212{
213 int comadj;
214
215 /* Initialize Internal Logic & Port */
216 corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
217 PICTRL_POWER_DOWN | PICTRL_INIOFF |
218 PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF |
219 PICTRL_DAC_SIGNAL_OFF);
220
221 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
222 POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF |
223 POWER0_COM_OFF | POWER0_VCC5_OFF);
224
225 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
226 POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
227
228 /* VDD(+8V), SVSS(-4V) ON */
229 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
230 POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
231 mdelay(3);
232
233 /* DAC ON */
234 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
235 POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
236 POWER0_COM_OFF | POWER0_VCC5_OFF);
237
238 /* INIB = H, INI = L */
239 /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
240 corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
241 PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
242
243 /* Set Common Voltage */
244 comadj = sharpsl_param.comadj;
245 if (comadj < 0)
246 comadj = DEFAULT_COMADJ;
247
248 lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF |
249 POWER0_VCC5_OFF, comadj);
250
251 /* VCC5 ON, DAC ON */
252 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
253 POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
254 POWER0_COM_OFF | POWER0_VCC5_ON);
255
256 /* GVSS(-8V) ON, VDD ON */
257 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
258 POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
259 mdelay(2);
260
261 /* COM SIGNAL ON (PICTL[3] = L) */
262 corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_INIT_STATE);
263
264 /* COM ON, DAC ON, VCC5_ON */
265 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
266 POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
267 POWER0_COM_ON | POWER0_VCC5_ON);
268
269 /* VW ON, GVSS ON, VDD ON */
270 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
271 POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
272
273 /* Signals output enable */
274 corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, 0);
275
276 /* Set Phase Adjust */
277 lcdtg_set_phadadj(lcd, lcd->mode);
278
279 /* Initialize for Input Signals from ATI */
280 corgi_ssp_lcdtg_send(lcd, POLCTRL_ADRS,
281 POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE |
282 POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L |
283 POLCTRL_EN_ACT_H);
284 udelay(1000);
285
286 switch (lcd->mode) {
287 case CORGI_LCD_MODE_VGA:
288 corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA);
289 break;
290 case CORGI_LCD_MODE_QVGA:
291 default:
292 corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA);
293 break;
294 }
295}
296
297static void corgi_lcd_power_off(struct corgi_lcd *lcd)
298{
299 /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
300 msleep(34);
301
302 /* (1)VW OFF */
303 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
304 POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
305
306 /* (2)COM OFF */
307 corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
308 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
309 POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
310
311 /* (3)Set Common Voltage Bias 0V */
312 lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF |
313 POWER0_VCC5_ON, 0);
314
315 /* (4)GVSS OFF */
316 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
317 POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
318
319 /* (5)VCC5 OFF */
320 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
321 POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
322
323 /* (6)Set PDWN, INIOFF, DACOFF */
324 corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
325 PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
326 PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
327
328 /* (7)DAC OFF */
329 corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
330 POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
331
332 /* (8)VDD OFF */
333 corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
334 POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
335}
336
337static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m)
338{
339 struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
340 int mode = CORGI_LCD_MODE_QVGA;
341
342 if (m->xres == 640 || m->xres == 480)
343 mode = CORGI_LCD_MODE_VGA;
344
345 if (lcd->mode == mode)
346 return 0;
347
348 lcdtg_set_phadadj(lcd, mode);
349
350 switch (mode) {
351 case CORGI_LCD_MODE_VGA:
352 corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA);
353 break;
354 case CORGI_LCD_MODE_QVGA:
355 default:
356 corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA);
357 break;
358 }
359
360 lcd->mode = mode;
361 return 0;
362}
363
364static int corgi_lcd_set_power(struct lcd_device *ld, int power)
365{
366 struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
367
368 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
369 corgi_lcd_power_on(lcd);
370
371 if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
372 corgi_lcd_power_off(lcd);
373
374 lcd->power = power;
375 return 0;
376}
377
378static int corgi_lcd_get_power(struct lcd_device *ld)
379{
380 struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
381
382 return lcd->power;
383}
384
385static struct lcd_ops corgi_lcd_ops = {
386 .get_power = corgi_lcd_get_power,
387 .set_power = corgi_lcd_set_power,
388 .set_mode = corgi_lcd_set_mode,
389};
390
391static int corgi_bl_get_intensity(struct backlight_device *bd)
392{
393 struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev);
394
395 return lcd->intensity;
396}
397
398static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity)
399{
400 int cont;
401
402 if (intensity > 0x10)
403 intensity += 0x10;
404
405 corgi_ssp_lcdtg_send(lcd, DUTYCTRL_ADRS, intensity);
406
407 /* Bit 5 via GPIO_BACKLIGHT_CONT */
408 cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted;
409
410 if (gpio_is_valid(lcd->gpio_backlight_cont))
411 gpio_set_value(lcd->gpio_backlight_cont, cont);
412
413 if (gpio_is_valid(lcd->gpio_backlight_on))
414 gpio_set_value(lcd->gpio_backlight_on, intensity);
415
416 if (lcd->kick_battery)
417 lcd->kick_battery();
418
419 lcd->intensity = intensity;
420 return 0;
421}
422
423static int corgi_bl_update_status(struct backlight_device *bd)
424{
425 struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev);
426 int intensity = bd->props.brightness;
427
428 if (bd->props.power != FB_BLANK_UNBLANK)
429 intensity = 0;
430
431 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
432 intensity = 0;
433
434 if (corgibl_flags & CORGIBL_SUSPENDED)
435 intensity = 0;
436 if (corgibl_flags & CORGIBL_BATTLOW)
437 intensity &= lcd->limit_mask;
438
439 return corgi_bl_set_intensity(lcd, intensity);
440}
441
442void corgibl_limit_intensity(int limit)
443{
444 if (limit)
445 corgibl_flags |= CORGIBL_BATTLOW;
446 else
447 corgibl_flags &= ~CORGIBL_BATTLOW;
448
449 backlight_update_status(the_corgi_lcd->bl_dev);
450}
451EXPORT_SYMBOL(corgibl_limit_intensity);
452
453static struct backlight_ops corgi_bl_ops = {
454 .get_brightness = corgi_bl_get_intensity,
455 .update_status = corgi_bl_update_status,
456};
457
458#ifdef CONFIG_PM
459static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state)
460{
461 struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
462
463 corgibl_flags |= CORGIBL_SUSPENDED;
464 corgi_bl_set_intensity(lcd, 0);
465 corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
466 return 0;
467}
468
469static int corgi_lcd_resume(struct spi_device *spi)
470{
471 struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
472
473 corgibl_flags &= ~CORGIBL_SUSPENDED;
474 corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
475 backlight_update_status(lcd->bl_dev);
476 return 0;
477}
478#else
479#define corgi_lcd_suspend NULL
480#define corgi_lcd_resume NULL
481#endif
482
483static int setup_gpio_backlight(struct corgi_lcd *lcd,
484 struct corgi_lcd_platform_data *pdata)
485{
486 struct spi_device *spi = lcd->spi_dev;
487 int err;
488
489 lcd->gpio_backlight_on = -1;
490 lcd->gpio_backlight_cont = -1;
491
492 if (gpio_is_valid(pdata->gpio_backlight_on)) {
493 err = gpio_request(pdata->gpio_backlight_on, "BL_ON");
494 if (err) {
495 dev_err(&spi->dev, "failed to request GPIO%d for "
496 "backlight_on\n", pdata->gpio_backlight_on);
497 return err;
498 }
499
500 lcd->gpio_backlight_on = pdata->gpio_backlight_on;
501 gpio_direction_output(lcd->gpio_backlight_on, 0);
502 }
503
504 if (gpio_is_valid(pdata->gpio_backlight_cont)) {
505 err = gpio_request(pdata->gpio_backlight_cont, "BL_CONT");
506 if (err) {
507 dev_err(&spi->dev, "failed to request GPIO%d for "
508 "backlight_cont\n", pdata->gpio_backlight_cont);
509 goto err_free_backlight_on;
510 }
511
512 lcd->gpio_backlight_cont = pdata->gpio_backlight_cont;
513
514 /* spitz and akita use both GPIOs for backlight, and
515 * have inverted polarity of GPIO_BACKLIGHT_CONT
516 */
517 if (gpio_is_valid(lcd->gpio_backlight_on)) {
518 lcd->gpio_backlight_cont_inverted = 1;
519 gpio_direction_output(lcd->gpio_backlight_cont, 1);
520 } else {
521 lcd->gpio_backlight_cont_inverted = 0;
522 gpio_direction_output(lcd->gpio_backlight_cont, 0);
523 }
524 }
525 return 0;
526
527err_free_backlight_on:
528 if (gpio_is_valid(lcd->gpio_backlight_on))
529 gpio_free(lcd->gpio_backlight_on);
530 return err;
531}
532
533static int __devinit corgi_lcd_probe(struct spi_device *spi)
534{
535 struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
536 struct corgi_lcd *lcd;
537 int ret = 0;
538
539 if (pdata == NULL) {
540 dev_err(&spi->dev, "platform data not available\n");
541 return -EINVAL;
542 }
543
544 lcd = kzalloc(sizeof(struct corgi_lcd), GFP_KERNEL);
545 if (!lcd) {
546 dev_err(&spi->dev, "failed to allocate memory\n");
547 return -ENOMEM;
548 }
549
550 lcd->spi_dev = spi;
551
552 lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
553 lcd, &corgi_lcd_ops);
554 if (IS_ERR(lcd->lcd_dev)) {
555 ret = PTR_ERR(lcd->lcd_dev);
556 goto err_free_lcd;
557 }
558 lcd->power = FB_BLANK_POWERDOWN;
559 lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
560
561 lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev,
562 lcd, &corgi_bl_ops);
563 if (IS_ERR(lcd->bl_dev)) {
564 ret = PTR_ERR(lcd->bl_dev);
565 goto err_unregister_lcd;
566 }
567 lcd->bl_dev->props.max_brightness = pdata->max_intensity;
568 lcd->bl_dev->props.brightness = pdata->default_intensity;
569 lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
570
571 ret = setup_gpio_backlight(lcd, pdata);
572 if (ret)
573 goto err_unregister_bl;
574
575 lcd->kick_battery = pdata->kick_battery;
576
577 dev_set_drvdata(&spi->dev, lcd);
578 corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
579 backlight_update_status(lcd->bl_dev);
580
581 lcd->limit_mask = pdata->limit_mask;
582 the_corgi_lcd = lcd;
583 return 0;
584
585err_unregister_bl:
586 backlight_device_unregister(lcd->bl_dev);
587err_unregister_lcd:
588 lcd_device_unregister(lcd->lcd_dev);
589err_free_lcd:
590 kfree(lcd);
591 return ret;
592}
593
594static int __devexit corgi_lcd_remove(struct spi_device *spi)
595{
596 struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
597
598 lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
599 lcd->bl_dev->props.brightness = 0;
600 backlight_update_status(lcd->bl_dev);
601 backlight_device_unregister(lcd->bl_dev);
602
603 if (gpio_is_valid(lcd->gpio_backlight_on))
604 gpio_free(lcd->gpio_backlight_on);
605
606 if (gpio_is_valid(lcd->gpio_backlight_cont))
607 gpio_free(lcd->gpio_backlight_cont);
608
609 corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
610 lcd_device_unregister(lcd->lcd_dev);
611 kfree(lcd);
612
613 return 0;
614}
615
616static struct spi_driver corgi_lcd_driver = {
617 .driver = {
618 .name = "corgi-lcd",
619 .owner = THIS_MODULE,
620 },
621 .probe = corgi_lcd_probe,
622 .remove = __devexit_p(corgi_lcd_remove),
623 .suspend = corgi_lcd_suspend,
624 .resume = corgi_lcd_resume,
625};
626
627static int __init corgi_lcd_init(void)
628{
629 return spi_register_driver(&corgi_lcd_driver);
630}
631module_init(corgi_lcd_init);
632
633static void __exit corgi_lcd_exit(void)
634{
635 spi_unregister_driver(&corgi_lcd_driver);
636}
637module_exit(corgi_lcd_exit);
638
639MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00");
640MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
641MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c
new file mode 100644
index 000000000000..242c38250166
--- /dev/null
+++ b/drivers/video/backlight/da903x.c
@@ -0,0 +1,201 @@
1/*
2 * Backlight driver for Dialog Semiconductor DA9030/DA9034
3 *
4 * Copyright (C) 2008 Compulab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il>
6 *
7 * Copyright (C) 2006-2008 Marvell International Ltd.
8 * Eric Miao <eric.miao@marvell.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/platform_device.h>
18#include <linux/fb.h>
19#include <linux/backlight.h>
20#include <linux/mfd/da903x.h>
21
22#define DA9030_WLED_CONTROL 0x25
23#define DA9030_WLED_CP_EN (1 << 6)
24#define DA9030_WLED_TRIM(x) ((x) & 0x7)
25
26#define DA9034_WLED_CONTROL1 0x3C
27#define DA9034_WLED_CONTROL2 0x3D
28
29#define DA9034_WLED_BOOST_EN (1 << 5)
30
31#define DA9030_MAX_BRIGHTNESS 7
32#define DA9034_MAX_BRIGHTNESS 0x7f
33
34struct da903x_backlight_data {
35 struct device *da903x_dev;
36 int id;
37 int current_brightness;
38};
39
40static int da903x_backlight_set(struct backlight_device *bl, int brightness)
41{
42 struct da903x_backlight_data *data = bl_get_data(bl);
43 struct device *dev = data->da903x_dev;
44 uint8_t val;
45 int ret = 0;
46
47 switch (data->id) {
48 case DA9034_ID_WLED:
49 ret = da903x_update(dev, DA9034_WLED_CONTROL1,
50 brightness, 0x7f);
51 if (ret)
52 return ret;
53
54 if (data->current_brightness && brightness == 0)
55 ret = da903x_clr_bits(dev,
56 DA9034_WLED_CONTROL2,
57 DA9034_WLED_BOOST_EN);
58
59 if (data->current_brightness == 0 && brightness)
60 ret = da903x_set_bits(dev,
61 DA9034_WLED_CONTROL2,
62 DA9034_WLED_BOOST_EN);
63 break;
64 case DA9030_ID_WLED:
65 val = DA9030_WLED_TRIM(brightness);
66 val |= brightness ? DA9030_WLED_CP_EN : 0;
67 ret = da903x_write(dev, DA9030_WLED_CONTROL, val);
68 break;
69 }
70
71 if (ret)
72 return ret;
73
74 data->current_brightness = brightness;
75 return 0;
76}
77
78static int da903x_backlight_update_status(struct backlight_device *bl)
79{
80 int brightness = bl->props.brightness;
81
82 if (bl->props.power != FB_BLANK_UNBLANK)
83 brightness = 0;
84
85 if (bl->props.fb_blank != FB_BLANK_UNBLANK)
86 brightness = 0;
87
88 return da903x_backlight_set(bl, brightness);
89}
90
91static int da903x_backlight_get_brightness(struct backlight_device *bl)
92{
93 struct da903x_backlight_data *data = bl_get_data(bl);
94 return data->current_brightness;
95}
96
97static struct backlight_ops da903x_backlight_ops = {
98 .update_status = da903x_backlight_update_status,
99 .get_brightness = da903x_backlight_get_brightness,
100};
101
102static int da903x_backlight_probe(struct platform_device *pdev)
103{
104 struct da903x_backlight_data *data;
105 struct backlight_device *bl;
106 int max_brightness;
107
108 data = kzalloc(sizeof(*data), GFP_KERNEL);
109 if (data == NULL)
110 return -ENOMEM;
111
112 switch (pdev->id) {
113 case DA9030_ID_WLED:
114 max_brightness = DA9030_MAX_BRIGHTNESS;
115 break;
116 case DA9034_ID_WLED:
117 max_brightness = DA9034_MAX_BRIGHTNESS;
118 break;
119 default:
120 dev_err(&pdev->dev, "invalid backlight device ID(%d)\n",
121 pdev->id);
122 return -EINVAL;
123 }
124
125 data->id = pdev->id;
126 data->da903x_dev = pdev->dev.parent;
127 data->current_brightness = 0;
128
129 bl = backlight_device_register(pdev->name, data->da903x_dev,
130 data, &da903x_backlight_ops);
131 if (IS_ERR(bl)) {
132 dev_err(&pdev->dev, "failed to register backlight\n");
133 return PTR_ERR(bl);
134 }
135
136 bl->props.max_brightness = max_brightness;
137 bl->props.brightness = max_brightness;
138
139 platform_set_drvdata(pdev, bl);
140 backlight_update_status(bl);
141 return 0;
142}
143
144static int da903x_backlight_remove(struct platform_device *pdev)
145{
146 struct backlight_device *bl = platform_get_drvdata(pdev);
147 struct da903x_backlight_data *data = bl_get_data(bl);
148
149 backlight_device_unregister(bl);
150 kfree(data);
151 return 0;
152}
153
154#ifdef CONFIG_PM
155static int da903x_backlight_suspend(struct platform_device *pdev,
156 pm_message_t state)
157{
158 struct backlight_device *bl = platform_get_drvdata(pdev);
159 return da903x_backlight_set(bl, 0);
160}
161
162static int da903x_backlight_resume(struct platform_device *pdev)
163{
164 struct backlight_device *bl = platform_get_drvdata(pdev);
165
166 backlight_update_status(bl);
167 return 0;
168}
169#else
170#define da903x_backlight_suspend NULL
171#define da903x_backlight_resume NULL
172#endif
173
174static struct platform_driver da903x_backlight_driver = {
175 .driver = {
176 .name = "da903x-backlight",
177 .owner = THIS_MODULE,
178 },
179 .probe = da903x_backlight_probe,
180 .remove = da903x_backlight_remove,
181 .suspend = da903x_backlight_suspend,
182 .resume = da903x_backlight_resume,
183};
184
185static int __init da903x_backlight_init(void)
186{
187 return platform_driver_register(&da903x_backlight_driver);
188}
189module_init(da903x_backlight_init);
190
191static void __exit da903x_backlight_exit(void)
192{
193 platform_driver_unregister(&da903x_backlight_driver);
194}
195module_exit(da903x_backlight_exit);
196
197MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
198MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
199 "Mike Rapoport <mike@compulab.co.il>");
200MODULE_LICENSE("GPL");
201MODULE_ALIAS("platform:da903x-backlight");
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index fbea2bd129c7..d4cfed0b26d5 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -18,8 +18,8 @@
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/backlight.h> 19#include <linux/backlight.h>
20 20
21#include <asm/cpu/dac.h> 21#include <cpu/dac.h>
22#include <asm/hp6xx.h> 22#include <mach/hp6xx.h>
23#include <asm/hd64461.h> 23#include <asm/hd64461.h>
24 24
25#define HP680_MAX_INTENSITY 255 25#define HP680_MAX_INTENSITY 255
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
new file mode 100644
index 000000000000..ba89b41b639c
--- /dev/null
+++ b/drivers/video/backlight/ili9320.c
@@ -0,0 +1,330 @@
1/* drivers/video/backlight/ili9320.c
2 *
3 * ILI9320 LCD controller driver core.
4 *
5 * Copyright 2007 Simtec Electronics
6 * http://armlinux.simtec.co.uk/
7 * Ben Dooks <ben@simtec.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/fb.h>
17#include <linux/init.h>
18#include <linux/lcd.h>
19#include <linux/module.h>
20
21#include <linux/spi/spi.h>
22
23#include <video/ili9320.h>
24
25#include "ili9320.h"
26
27
28static inline int ili9320_write_spi(struct ili9320 *ili,
29 unsigned int reg,
30 unsigned int value)
31{
32 struct ili9320_spi *spi = &ili->access.spi;
33 unsigned char *addr = spi->buffer_addr;
34 unsigned char *data = spi->buffer_data;
35
36 /* spi message consits of:
37 * first byte: ID and operation
38 */
39
40 addr[0] = spi->id | ILI9320_SPI_INDEX | ILI9320_SPI_WRITE;
41 addr[1] = reg >> 8;
42 addr[2] = reg;
43
44 /* second message is the data to transfer */
45
46 data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE;
47 data[1] = value >> 8;
48 data[2] = value;
49
50 return spi_sync(spi->dev, &spi->message);
51}
52
53int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
54{
55 dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
56 return ili->write(ili, reg, value);
57}
58
59EXPORT_SYMBOL_GPL(ili9320_write);
60
61int ili9320_write_regs(struct ili9320 *ili,
62 struct ili9320_reg *values,
63 int nr_values)
64{
65 int index;
66 int ret;
67
68 for (index = 0; index < nr_values; index++, values++) {
69 ret = ili9320_write(ili, values->address, values->value);
70 if (ret != 0)
71 return ret;
72 }
73
74 return 0;
75}
76
77EXPORT_SYMBOL_GPL(ili9320_write_regs);
78
79static void ili9320_reset(struct ili9320 *lcd)
80{
81 struct ili9320_platdata *cfg = lcd->platdata;
82
83 cfg->reset(1);
84 mdelay(50);
85
86 cfg->reset(0);
87 mdelay(50);
88
89 cfg->reset(1);
90 mdelay(100);
91}
92
93static inline int ili9320_init_chip(struct ili9320 *lcd)
94{
95 int ret;
96
97 ili9320_reset(lcd);
98
99 ret = lcd->client->init(lcd, lcd->platdata);
100 if (ret != 0) {
101 dev_err(lcd->dev, "failed to initialise display\n");
102 return ret;
103 }
104
105 lcd->initialised = 1;
106 return 0;
107}
108
109static inline int ili9320_power_on(struct ili9320 *lcd)
110{
111 if (!lcd->initialised)
112 ili9320_init_chip(lcd);
113
114 lcd->display1 |= (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
115 ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
116
117 return 0;
118}
119
120static inline int ili9320_power_off(struct ili9320 *lcd)
121{
122 lcd->display1 &= ~(ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
123 ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
124
125 return 0;
126}
127
128#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
129
130static int ili9320_power(struct ili9320 *lcd, int power)
131{
132 int ret = 0;
133
134 dev_dbg(lcd->dev, "power %d => %d\n", lcd->power, power);
135
136 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
137 ret = ili9320_power_on(lcd);
138 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
139 ret = ili9320_power_off(lcd);
140
141 if (ret == 0)
142 lcd->power = power;
143 else
144 dev_warn(lcd->dev, "failed to set power mode %d\n", power);
145
146 return ret;
147}
148
149static inline struct ili9320 *to_our_lcd(struct lcd_device *lcd)
150{
151 return lcd_get_data(lcd);
152}
153
154static int ili9320_set_power(struct lcd_device *ld, int power)
155{
156 struct ili9320 *lcd = to_our_lcd(ld);
157
158 return ili9320_power(lcd, power);
159}
160
161static int ili9320_get_power(struct lcd_device *ld)
162{
163 struct ili9320 *lcd = to_our_lcd(ld);
164
165 return lcd->power;
166}
167
168static struct lcd_ops ili9320_ops = {
169 .get_power = ili9320_get_power,
170 .set_power = ili9320_set_power,
171};
172
173static void __devinit ili9320_setup_spi(struct ili9320 *ili,
174 struct spi_device *dev)
175{
176 struct ili9320_spi *spi = &ili->access.spi;
177
178 ili->write = ili9320_write_spi;
179 spi->dev = dev;
180
181 /* fill the two messages we are going to use to send the data
182 * with, the first the address followed by the data. The datasheet
183 * says they should be done as two distinct cycles of the SPI CS line.
184 */
185
186 spi->xfer[0].tx_buf = spi->buffer_addr;
187 spi->xfer[1].tx_buf = spi->buffer_data;
188 spi->xfer[0].len = 3;
189 spi->xfer[1].len = 3;
190 spi->xfer[0].bits_per_word = 8;
191 spi->xfer[1].bits_per_word = 8;
192 spi->xfer[0].cs_change = 1;
193
194 spi_message_init(&spi->message);
195 spi_message_add_tail(&spi->xfer[0], &spi->message);
196 spi_message_add_tail(&spi->xfer[1], &spi->message);
197}
198
199int __devinit ili9320_probe_spi(struct spi_device *spi,
200 struct ili9320_client *client)
201{
202 struct ili9320_platdata *cfg = spi->dev.platform_data;
203 struct device *dev = &spi->dev;
204 struct ili9320 *ili;
205 struct lcd_device *lcd;
206 int ret = 0;
207
208 /* verify we where given some information */
209
210 if (cfg == NULL) {
211 dev_err(dev, "no platform data supplied\n");
212 return -EINVAL;
213 }
214
215 if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
216 dev_err(dev, "invalid platform data supplied\n");
217 return -EINVAL;
218 }
219
220 /* allocate and initialse our state */
221
222 ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
223 if (ili == NULL) {
224 dev_err(dev, "no memory for device\n");
225 return -ENOMEM;
226 }
227
228 ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
229
230 ili->dev = dev;
231 ili->client = client;
232 ili->power = FB_BLANK_POWERDOWN;
233 ili->platdata = cfg;
234
235 dev_set_drvdata(&spi->dev, ili);
236
237 ili9320_setup_spi(ili, spi);
238
239 lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
240 if (IS_ERR(lcd)) {
241 dev_err(dev, "failed to register lcd device\n");
242 ret = PTR_ERR(lcd);
243 goto err_free;
244 }
245
246 ili->lcd = lcd;
247
248 dev_info(dev, "initialising %s\n", client->name);
249
250 ret = ili9320_power(ili, FB_BLANK_UNBLANK);
251 if (ret != 0) {
252 dev_err(dev, "failed to set lcd power state\n");
253 goto err_unregister;
254 }
255
256 return 0;
257
258 err_unregister:
259 lcd_device_unregister(lcd);
260
261 err_free:
262 kfree(ili);
263
264 return ret;
265}
266
267EXPORT_SYMBOL_GPL(ili9320_probe_spi);
268
269int __devexit ili9320_remove(struct ili9320 *ili)
270{
271 ili9320_power(ili, FB_BLANK_POWERDOWN);
272
273 lcd_device_unregister(ili->lcd);
274 kfree(ili);
275
276 return 0;
277}
278
279EXPORT_SYMBOL_GPL(ili9320_remove);
280
281#ifdef CONFIG_PM
282int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
283{
284 int ret;
285
286 dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event);
287
288 if (state.event == PM_EVENT_SUSPEND) {
289 ret = ili9320_power(lcd, FB_BLANK_POWERDOWN);
290
291 if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
292 ili9320_write(lcd, ILI9320_POWER1, lcd->power1 |
293 ILI9320_POWER1_SLP |
294 ILI9320_POWER1_DSTB);
295 lcd->initialised = 0;
296 }
297
298 return ret;
299 }
300
301 return 0;
302}
303
304EXPORT_SYMBOL_GPL(ili9320_suspend);
305
306int ili9320_resume(struct ili9320 *lcd)
307{
308 dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
309
310 if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
311 ili9320_write(lcd, ILI9320_POWER1, 0x00);
312 }
313
314 return ili9320_power(lcd, FB_BLANK_UNBLANK);
315}
316
317EXPORT_SYMBOL_GPL(ili9320_resume);
318#endif
319
320/* Power down all displays on reboot, poweroff or halt */
321void ili9320_shutdown(struct ili9320 *lcd)
322{
323 ili9320_power(lcd, FB_BLANK_POWERDOWN);
324}
325
326EXPORT_SYMBOL_GPL(ili9320_shutdown);
327
328MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
329MODULE_DESCRIPTION("ILI9320 LCD Driver");
330MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
new file mode 100644
index 000000000000..e388eca7cac5
--- /dev/null
+++ b/drivers/video/backlight/ili9320.h
@@ -0,0 +1,80 @@
1/* drivers/video/backlight/ili9320.h
2 *
3 * ILI9320 LCD controller driver core.
4 *
5 * Copyright 2007 Simtec Electronics
6 * Ben Dooks <ben@simtec.co.uk>
7 *
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15/* Holder for register and value pairs. */
16struct ili9320_reg {
17 unsigned short address;
18 unsigned short value;
19};
20
21struct ili9320;
22
23struct ili9320_client {
24 const char *name;
25 int (*init)(struct ili9320 *ili, struct ili9320_platdata *cfg);
26
27};
28/* Device attached via an SPI bus. */
29struct ili9320_spi {
30 struct spi_device *dev;
31 struct spi_message message;
32 struct spi_transfer xfer[2];
33
34 unsigned char id;
35 unsigned char buffer_addr[4];
36 unsigned char buffer_data[4];
37};
38
39/* ILI9320 device state. */
40struct ili9320 {
41 union {
42 struct ili9320_spi spi; /* SPI attachged device. */
43 } access; /* Register access method. */
44
45 struct device *dev;
46 struct lcd_device *lcd; /* LCD device we created. */
47 struct ili9320_client *client;
48 struct ili9320_platdata *platdata;
49
50 int power; /* current power state. */
51 int initialised;
52
53 unsigned short display1;
54 unsigned short power1;
55
56 int (*write)(struct ili9320 *ili, unsigned int reg, unsigned int val);
57};
58
59
60/* ILI9320 register access routines */
61
62extern int ili9320_write(struct ili9320 *ili,
63 unsigned int reg, unsigned int value);
64
65extern int ili9320_write_regs(struct ili9320 *ili,
66 struct ili9320_reg *values,
67 int nr_values);
68
69/* Device probe */
70
71extern int ili9320_probe_spi(struct spi_device *spi,
72 struct ili9320_client *cli);
73
74extern int ili9320_remove(struct ili9320 *lcd);
75extern void ili9320_shutdown(struct ili9320 *lcd);
76
77/* PM */
78
79extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state);
80extern int ili9320_resume(struct ili9320 *lcd);
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
new file mode 100644
index 000000000000..a38fda1742dd
--- /dev/null
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -0,0 +1,204 @@
1/*
2 * Backlight Driver for the KB3886 Backlight
3 *
4 * Copyright (c) 2007-2008 Claudio Nieder
5 *
6 * Based on corgi_bl.c by Richard Purdie and kb3886 driver by Robert Woerle
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/platform_device.h>
18#include <linux/mutex.h>
19#include <linux/fb.h>
20#include <linux/backlight.h>
21#include <linux/delay.h>
22#include <linux/dmi.h>
23
24#define KB3886_PARENT 0x64
25#define KB3886_IO 0x60
26#define KB3886_ADC_DAC_PWM 0xC4
27#define KB3886_PWM0_WRITE 0x81
28#define KB3886_PWM0_READ 0x41
29
30static DEFINE_MUTEX(bl_mutex);
31
32static void kb3886_bl_set_intensity(int intensity)
33{
34 mutex_lock(&bl_mutex);
35 intensity = intensity&0xff;
36 outb(KB3886_ADC_DAC_PWM, KB3886_PARENT);
37 msleep(10);
38 outb(KB3886_PWM0_WRITE, KB3886_IO);
39 msleep(10);
40 outb(intensity, KB3886_IO);
41 mutex_unlock(&bl_mutex);
42}
43
44struct kb3886bl_machinfo {
45 int max_intensity;
46 int default_intensity;
47 int limit_mask;
48 void (*set_bl_intensity)(int intensity);
49};
50
51static struct kb3886bl_machinfo kb3886_bl_machinfo = {
52 .max_intensity = 0xff,
53 .default_intensity = 0xa0,
54 .limit_mask = 0x7f,
55 .set_bl_intensity = kb3886_bl_set_intensity,
56};
57
58static struct platform_device kb3886bl_device = {
59 .name = "kb3886-bl",
60 .dev = {
61 .platform_data = &kb3886_bl_machinfo,
62 },
63 .id = -1,
64};
65
66static struct platform_device *devices[] __initdata = {
67 &kb3886bl_device,
68};
69
70/*
71 * Back to driver
72 */
73
74static int kb3886bl_intensity;
75static struct backlight_device *kb3886_backlight_device;
76static struct kb3886bl_machinfo *bl_machinfo;
77
78static unsigned long kb3886bl_flags;
79#define KB3886BL_SUSPENDED 0x01
80
81static struct dmi_system_id __initdata kb3886bl_device_table[] = {
82 {
83 .ident = "Sahara Touch-iT",
84 .matches = {
85 DMI_MATCH(DMI_SYS_VENDOR, "SDV"),
86 DMI_MATCH(DMI_PRODUCT_NAME, "iTouch T201"),
87 },
88 },
89 { }
90};
91
92static int kb3886bl_send_intensity(struct backlight_device *bd)
93{
94 int intensity = bd->props.brightness;
95
96 if (bd->props.power != FB_BLANK_UNBLANK)
97 intensity = 0;
98 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
99 intensity = 0;
100 if (kb3886bl_flags & KB3886BL_SUSPENDED)
101 intensity = 0;
102
103 bl_machinfo->set_bl_intensity(intensity);
104
105 kb3886bl_intensity = intensity;
106 return 0;
107}
108
109#ifdef CONFIG_PM
110static int kb3886bl_suspend(struct platform_device *pdev, pm_message_t state)
111{
112 struct backlight_device *bd = platform_get_drvdata(pdev);
113
114 kb3886bl_flags |= KB3886BL_SUSPENDED;
115 backlight_update_status(bd);
116 return 0;
117}
118
119static int kb3886bl_resume(struct platform_device *pdev)
120{
121 struct backlight_device *bd = platform_get_drvdata(pdev);
122
123 kb3886bl_flags &= ~KB3886BL_SUSPENDED;
124 backlight_update_status(bd);
125 return 0;
126}
127#else
128#define kb3886bl_suspend NULL
129#define kb3886bl_resume NULL
130#endif
131
132static int kb3886bl_get_intensity(struct backlight_device *bd)
133{
134 return kb3886bl_intensity;
135}
136
137static struct backlight_ops kb3886bl_ops = {
138 .get_brightness = kb3886bl_get_intensity,
139 .update_status = kb3886bl_send_intensity,
140};
141
142static int kb3886bl_probe(struct platform_device *pdev)
143{
144 struct kb3886bl_machinfo *machinfo = pdev->dev.platform_data;
145
146 bl_machinfo = machinfo;
147 if (!machinfo->limit_mask)
148 machinfo->limit_mask = -1;
149
150 kb3886_backlight_device = backlight_device_register("kb3886-bl",
151 &pdev->dev, NULL, &kb3886bl_ops);
152 if (IS_ERR(kb3886_backlight_device))
153 return PTR_ERR(kb3886_backlight_device);
154
155 platform_set_drvdata(pdev, kb3886_backlight_device);
156
157 kb3886_backlight_device->props.max_brightness = machinfo->max_intensity;
158 kb3886_backlight_device->props.power = FB_BLANK_UNBLANK;
159 kb3886_backlight_device->props.brightness = machinfo->default_intensity;
160 backlight_update_status(kb3886_backlight_device);
161
162 return 0;
163}
164
165static int kb3886bl_remove(struct platform_device *pdev)
166{
167 struct backlight_device *bd = platform_get_drvdata(pdev);
168
169 backlight_device_unregister(bd);
170
171 return 0;
172}
173
174static struct platform_driver kb3886bl_driver = {
175 .probe = kb3886bl_probe,
176 .remove = kb3886bl_remove,
177 .suspend = kb3886bl_suspend,
178 .resume = kb3886bl_resume,
179 .driver = {
180 .name = "kb3886-bl",
181 },
182};
183
184static int __init kb3886_init(void)
185{
186 if (!dmi_check_system(kb3886bl_device_table))
187 return -ENODEV;
188
189 platform_add_devices(devices, ARRAY_SIZE(devices));
190 return platform_driver_register(&kb3886bl_driver);
191}
192
193static void __exit kb3886_exit(void)
194{
195 platform_driver_unregister(&kb3886bl_driver);
196}
197
198module_init(kb3886_init);
199module_exit(kb3886_exit);
200
201MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>");
202MODULE_DESCRIPTION("Tabletkiosk Sahara Touch-iT Backlight Driver");
203MODULE_LICENSE("GPL");
204MODULE_ALIAS("dmi:*:svnSDV:pniTouchT201:*");
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 299fd318dd45..8e1731d3b228 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -27,14 +27,26 @@ static int fb_notifier_callback(struct notifier_block *self,
27 struct fb_event *evdata = data; 27 struct fb_event *evdata = data;
28 28
29 /* If we aren't interested in this event, skip it immediately ... */ 29 /* If we aren't interested in this event, skip it immediately ... */
30 if (event != FB_EVENT_BLANK) 30 switch (event) {
31 case FB_EVENT_BLANK:
32 case FB_EVENT_MODE_CHANGE:
33 case FB_EVENT_MODE_CHANGE_ALL:
34 break;
35 default:
31 return 0; 36 return 0;
37 }
32 38
33 ld = container_of(self, struct lcd_device, fb_notif); 39 ld = container_of(self, struct lcd_device, fb_notif);
40 if (!ld->ops)
41 return 0;
42
34 mutex_lock(&ld->ops_lock); 43 mutex_lock(&ld->ops_lock);
35 if (ld->ops) 44 if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
36 if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info)) 45 if (event == FB_EVENT_BLANK)
37 ld->ops->set_power(ld, *(int *)evdata->data); 46 ld->ops->set_power(ld, *(int *)evdata->data);
47 else
48 ld->ops->set_mode(ld, evdata->data);
49 }
38 mutex_unlock(&ld->ops_lock); 50 mutex_unlock(&ld->ops_lock);
39 return 0; 51 return 0;
40} 52}
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
new file mode 100644
index 000000000000..06964af761c6
--- /dev/null
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -0,0 +1,114 @@
1/*
2 * Backlight Driver for Nvidia 8600 in Macbook Pro
3 *
4 * Copyright (c) Red Hat <mjg@redhat.com>
5 * Based on code from Pommed:
6 * Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
7 * Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
8 * Copyright (C) 2007 Julien BLACHE <jb@jblache.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * This driver triggers SMIs which cause the firmware to change the
15 * backlight brightness. This is icky in many ways, but it's impractical to
16 * get at the firmware code in order to figure out what it's actually doing.
17 */
18
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/platform_device.h>
23#include <linux/backlight.h>
24#include <linux/err.h>
25#include <linux/dmi.h>
26#include <linux/io.h>
27
28static struct backlight_device *mbp_backlight_device;
29
30static struct dmi_system_id __initdata mbp_device_table[] = {
31 {
32 .ident = "3,1",
33 .matches = {
34 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
35 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
36 },
37 },
38 {
39 .ident = "3,2",
40 .matches = {
41 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
42 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
43 },
44 },
45 {
46 .ident = "4,1",
47 .matches = {
48 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
49 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
50 },
51 },
52 { }
53};
54
55static int mbp_send_intensity(struct backlight_device *bd)
56{
57 int intensity = bd->props.brightness;
58
59 outb(0x04 | (intensity << 4), 0xb3);
60 outb(0xbf, 0xb2);
61
62 return 0;
63}
64
65static int mbp_get_intensity(struct backlight_device *bd)
66{
67 outb(0x03, 0xb3);
68 outb(0xbf, 0xb2);
69 return inb(0xb3) >> 4;
70}
71
72static struct backlight_ops mbp_ops = {
73 .get_brightness = mbp_get_intensity,
74 .update_status = mbp_send_intensity,
75};
76
77static int __init mbp_init(void)
78{
79 if (!dmi_check_system(mbp_device_table))
80 return -ENODEV;
81
82 if (!request_region(0xb2, 2, "Macbook Pro backlight"))
83 return -ENXIO;
84
85 mbp_backlight_device = backlight_device_register("mbp_backlight",
86 NULL, NULL,
87 &mbp_ops);
88 if (IS_ERR(mbp_backlight_device)) {
89 release_region(0xb2, 2);
90 return PTR_ERR(mbp_backlight_device);
91 }
92
93 mbp_backlight_device->props.max_brightness = 15;
94 mbp_backlight_device->props.brightness =
95 mbp_get_intensity(mbp_backlight_device);
96 backlight_update_status(mbp_backlight_device);
97
98 return 0;
99}
100
101static void __exit mbp_exit(void)
102{
103 backlight_device_unregister(mbp_backlight_device);
104
105 release_region(0xb2, 2);
106}
107
108module_init(mbp_init);
109module_exit(mbp_exit);
110
111MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
112MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
113MODULE_LICENSE("GPL");
114MODULE_DEVICE_TABLE(dmi, mbp_device_table);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 891875d53a49..cbad67e89826 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -25,9 +25,9 @@
25#include <linux/fb.h> 25#include <linux/fb.h>
26#include <linux/backlight.h> 26#include <linux/backlight.h>
27 27
28#include <asm/arch/hardware.h> 28#include <mach/hardware.h>
29#include <asm/arch/board.h> 29#include <mach/board.h>
30#include <asm/arch/mux.h> 30#include <mach/mux.h>
31 31
32#define OMAPBL_MAX_INTENSITY 0xff 32#define OMAPBL_MAX_INTENSITY 0xff
33 33
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
new file mode 100644
index 000000000000..738694d23889
--- /dev/null
+++ b/drivers/video/backlight/platform_lcd.c
@@ -0,0 +1,174 @@
1/* drivers/video/backlight/platform_lcd.c
2 *
3 * Copyright 2008 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Generic platform-device LCD power control interface.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12*/
13
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/fb.h>
17#include <linux/backlight.h>
18#include <linux/lcd.h>
19
20#include <video/platform_lcd.h>
21
22struct platform_lcd {
23 struct device *us;
24 struct lcd_device *lcd;
25 struct plat_lcd_data *pdata;
26
27 unsigned int power;
28 unsigned int suspended : 1;
29};
30
31static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
32{
33 return lcd_get_data(lcd);
34}
35
36static int platform_lcd_get_power(struct lcd_device *lcd)
37{
38 struct platform_lcd *plcd = to_our_lcd(lcd);
39
40 return plcd->power;
41}
42
43static int platform_lcd_set_power(struct lcd_device *lcd, int power)
44{
45 struct platform_lcd *plcd = to_our_lcd(lcd);
46 int lcd_power = 1;
47
48 if (power == FB_BLANK_POWERDOWN || plcd->suspended)
49 lcd_power = 0;
50
51 plcd->pdata->set_power(plcd->pdata, lcd_power);
52 plcd->power = power;
53
54 return 0;
55}
56
57static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info)
58{
59 struct platform_lcd *plcd = to_our_lcd(lcd);
60 struct plat_lcd_data *pdata = plcd->pdata;
61
62 if (pdata->match_fb)
63 return pdata->match_fb(pdata, info);
64
65 return plcd->us->parent == info->device;
66}
67
68static struct lcd_ops platform_lcd_ops = {
69 .get_power = platform_lcd_get_power,
70 .set_power = platform_lcd_set_power,
71 .check_fb = platform_lcd_match,
72};
73
74static int __devinit platform_lcd_probe(struct platform_device *pdev)
75{
76 struct plat_lcd_data *pdata;
77 struct platform_lcd *plcd;
78 struct device *dev = &pdev->dev;
79 int err;
80
81 pdata = pdev->dev.platform_data;
82 if (!pdata) {
83 dev_err(dev, "no platform data supplied\n");
84 return -EINVAL;
85 }
86
87 plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
88 if (!plcd) {
89 dev_err(dev, "no memory for state\n");
90 return -ENOMEM;
91 }
92
93 plcd->us = dev;
94 plcd->pdata = pdata;
95 plcd->lcd = lcd_device_register(dev_name(dev), dev,
96 plcd, &platform_lcd_ops);
97 if (IS_ERR(plcd->lcd)) {
98 dev_err(dev, "cannot register lcd device\n");
99 err = PTR_ERR(plcd->lcd);
100 goto err_mem;
101 }
102
103 platform_set_drvdata(pdev, plcd);
104 platform_lcd_set_power(plcd->lcd, FB_BLANK_NORMAL);
105
106 return 0;
107
108 err_mem:
109 kfree(plcd);
110 return err;
111}
112
113static int __devexit platform_lcd_remove(struct platform_device *pdev)
114{
115 struct platform_lcd *plcd = platform_get_drvdata(pdev);
116
117 lcd_device_unregister(plcd->lcd);
118 kfree(plcd);
119
120 return 0;
121}
122
123#ifdef CONFIG_PM
124static int platform_lcd_suspend(struct platform_device *pdev, pm_message_t st)
125{
126 struct platform_lcd *plcd = platform_get_drvdata(pdev);
127
128 plcd->suspended = 1;
129 platform_lcd_set_power(plcd->lcd, plcd->power);
130
131 return 0;
132}
133
134static int platform_lcd_resume(struct platform_device *pdev)
135{
136 struct platform_lcd *plcd = platform_get_drvdata(pdev);
137
138 plcd->suspended = 0;
139 platform_lcd_set_power(plcd->lcd, plcd->power);
140
141 return 0;
142}
143#else
144#define platform_lcd_suspend NULL
145#define platform_lcd_resume NULL
146#endif
147
148static struct platform_driver platform_lcd_driver = {
149 .driver = {
150 .name = "platform-lcd",
151 .owner = THIS_MODULE,
152 },
153 .probe = platform_lcd_probe,
154 .remove = __devexit_p(platform_lcd_remove),
155 .suspend = platform_lcd_suspend,
156 .resume = platform_lcd_resume,
157};
158
159static int __init platform_lcd_init(void)
160{
161 return platform_driver_register(&platform_lcd_driver);
162}
163
164static void __exit platform_lcd_cleanup(void)
165{
166 platform_driver_unregister(&platform_lcd_driver);
167}
168
169module_init(platform_lcd_init);
170module_exit(platform_lcd_cleanup);
171
172MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
173MODULE_LICENSE("GPL v2");
174MODULE_ALIAS("platform:platform-lcd");
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 6338d0e2fe07..ea07258565f0 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -68,8 +68,10 @@ static int pwm_backlight_probe(struct platform_device *pdev)
68 struct pwm_bl_data *pb; 68 struct pwm_bl_data *pb;
69 int ret; 69 int ret;
70 70
71 if (!data) 71 if (!data) {
72 dev_err(&pdev->dev, "failed to find platform data\n");
72 return -EINVAL; 73 return -EINVAL;
74 }
73 75
74 if (data->init) { 76 if (data->init) {
75 ret = data->init(&pdev->dev); 77 ret = data->init(&pdev->dev);
@@ -79,6 +81,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
79 81
80 pb = kzalloc(sizeof(*pb), GFP_KERNEL); 82 pb = kzalloc(sizeof(*pb), GFP_KERNEL);
81 if (!pb) { 83 if (!pb) {
84 dev_err(&pdev->dev, "no memory for state\n");
82 ret = -ENOMEM; 85 ret = -ENOMEM;
83 goto err_alloc; 86 goto err_alloc;
84 } 87 }
@@ -91,7 +94,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
91 dev_err(&pdev->dev, "unable to request PWM for backlight\n"); 94 dev_err(&pdev->dev, "unable to request PWM for backlight\n");
92 ret = PTR_ERR(pb->pwm); 95 ret = PTR_ERR(pb->pwm);
93 goto err_pwm; 96 goto err_pwm;
94 } 97 } else
98 dev_dbg(&pdev->dev, "got pwm for backlight\n");
95 99
96 bl = backlight_device_register(pdev->name, &pdev->dev, 100 bl = backlight_device_register(pdev->name, &pdev->dev,
97 pb, &pwm_backlight_ops); 101 pb, &pwm_backlight_ops);
@@ -183,3 +187,5 @@ module_exit(pwm_backlight_exit);
183 187
184MODULE_DESCRIPTION("PWM based Backlight Driver"); 188MODULE_DESCRIPTION("PWM based Backlight Driver");
185MODULE_LICENSE("GPL"); 189MODULE_LICENSE("GPL");
190MODULE_ALIAS("platform:pwm-backlight");
191
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
new file mode 100644
index 000000000000..8427669162ea
--- /dev/null
+++ b/drivers/video/backlight/tdo24m.c
@@ -0,0 +1,396 @@
1/*
2 * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
3 *
4 * Copyright (C) 2008 Marvell International Ltd.
5 * Eric Miao <eric.miao@marvell.com>
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 * publishhed by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/device.h>
16#include <linux/spi/spi.h>
17#include <linux/fb.h>
18#include <linux/lcd.h>
19
20#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
21
22#define TDO24M_SPI_BUFF_SIZE (4)
23#define MODE_QVGA 0
24#define MODE_VGA 1
25
26struct tdo24m {
27 struct spi_device *spi_dev;
28 struct lcd_device *lcd_dev;
29
30 struct spi_message msg;
31 struct spi_transfer xfer;
32 uint8_t *buf;
33
34 int power;
35 int mode;
36};
37
38/* use bit 30, 31 as the indicator of command parameter number */
39#define CMD0(x) ((0 << 30) | (x))
40#define CMD1(x, x1) ((1 << 30) | ((x) << 9) | 0x100 | (x1))
41#define CMD2(x, x1, x2) ((2 << 30) | ((x) << 18) | 0x20000 |\
42 ((x1) << 9) | 0x100 | (x2))
43#define CMD_NULL (-1)
44
45static uint32_t lcd_panel_reset[] = {
46 CMD0(0x1), /* reset */
47 CMD0(0x0), /* nop */
48 CMD0(0x0), /* nop */
49 CMD0(0x0), /* nop */
50 CMD_NULL,
51};
52
53static uint32_t lcd_panel_on[] = {
54 CMD0(0x29), /* Display ON */
55 CMD2(0xB8, 0xFF, 0xF9), /* Output Control */
56 CMD0(0x11), /* Sleep out */
57 CMD1(0xB0, 0x16), /* Wake */
58 CMD_NULL,
59};
60
61static uint32_t lcd_panel_off[] = {
62 CMD0(0x28), /* Display OFF */
63 CMD2(0xB8, 0x80, 0x02), /* Output Control */
64 CMD0(0x10), /* Sleep in */
65 CMD1(0xB0, 0x00), /* Deep stand by in */
66 CMD_NULL,
67};
68
69static uint32_t lcd_vga_pass_through[] = {
70 CMD1(0xB0, 0x16),
71 CMD1(0xBC, 0x80),
72 CMD1(0xE1, 0x00),
73 CMD1(0x36, 0x50),
74 CMD1(0x3B, 0x00),
75 CMD_NULL,
76};
77
78static uint32_t lcd_qvga_pass_through[] = {
79 CMD1(0xB0, 0x16),
80 CMD1(0xBC, 0x81),
81 CMD1(0xE1, 0x00),
82 CMD1(0x36, 0x50),
83 CMD1(0x3B, 0x22),
84 CMD_NULL,
85};
86
87static uint32_t lcd_vga_transfer[] = {
88 CMD1(0xcf, 0x02), /* Blanking period control (1) */
89 CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
90 CMD1(0xd1, 0x01), /* CKV timing control on/off */
91 CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */
92 CMD2(0xd3, 0x1a, 0x0f), /* OEV timing control */
93 CMD2(0xd4, 0x1f, 0xaf), /* ASW timing control (1) */
94 CMD1(0xd5, 0x14), /* ASW timing control (2) */
95 CMD0(0x21), /* Invert for normally black display */
96 CMD0(0x29), /* Display on */
97 CMD_NULL,
98};
99
100static uint32_t lcd_qvga_transfer[] = {
101 CMD1(0xd6, 0x02), /* Blanking period control (1) */
102 CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */
103 CMD1(0xd8, 0x01), /* CKV timing control on/off */
104 CMD2(0xd9, 0x00, 0x08), /* CKV 1,2 timing control */
105 CMD2(0xde, 0x05, 0x0a), /* OEV timing control */
106 CMD2(0xdf, 0x0a, 0x19), /* ASW timing control (1) */
107 CMD1(0xe0, 0x0a), /* ASW timing control (2) */
108 CMD0(0x21), /* Invert for normally black display */
109 CMD0(0x29), /* Display on */
110 CMD_NULL,
111};
112
113static uint32_t lcd_panel_config[] = {
114 CMD2(0xb8, 0xff, 0xf9), /* Output control */
115 CMD0(0x11), /* sleep out */
116 CMD1(0xba, 0x01), /* Display mode (1) */
117 CMD1(0xbb, 0x00), /* Display mode (2) */
118 CMD1(0x3a, 0x60), /* Display mode 18-bit RGB */
119 CMD1(0xbf, 0x10), /* Drive system change control */
120 CMD1(0xb1, 0x56), /* Booster operation setup */
121 CMD1(0xb2, 0x33), /* Booster mode setup */
122 CMD1(0xb3, 0x11), /* Booster frequency setup */
123 CMD1(0xb4, 0x02), /* Op amp/system clock */
124 CMD1(0xb5, 0x35), /* VCS voltage */
125 CMD1(0xb6, 0x40), /* VCOM voltage */
126 CMD1(0xb7, 0x03), /* External display signal */
127 CMD1(0xbd, 0x00), /* ASW slew rate */
128 CMD1(0xbe, 0x00), /* Dummy data for QuadData operation */
129 CMD1(0xc0, 0x11), /* Sleep out FR count (A) */
130 CMD1(0xc1, 0x11), /* Sleep out FR count (B) */
131 CMD1(0xc2, 0x11), /* Sleep out FR count (C) */
132 CMD2(0xc3, 0x20, 0x40), /* Sleep out FR count (D) */
133 CMD2(0xc4, 0x60, 0xc0), /* Sleep out FR count (E) */
134 CMD2(0xc5, 0x10, 0x20), /* Sleep out FR count (F) */
135 CMD1(0xc6, 0xc0), /* Sleep out FR count (G) */
136 CMD2(0xc7, 0x33, 0x43), /* Gamma 1 fine tuning (1) */
137 CMD1(0xc8, 0x44), /* Gamma 1 fine tuning (2) */
138 CMD1(0xc9, 0x33), /* Gamma 1 inclination adjustment */
139 CMD1(0xca, 0x00), /* Gamma 1 blue offset adjustment */
140 CMD2(0xec, 0x01, 0xf0), /* Horizontal clock cycles */
141 CMD_NULL,
142};
143
144static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array)
145{
146 struct spi_transfer *x = &lcd->xfer;
147 uint32_t data, *p = array;
148 int nparams, err = 0;
149
150 for (; *p != CMD_NULL; p++) {
151
152 nparams = (*p >> 30) & 0x3;
153
154 data = *p << (7 - nparams);
155 switch (nparams) {
156 case 0:
157 lcd->buf[0] = (data >> 8) & 0xff;
158 lcd->buf[1] = data & 0xff;
159 break;
160 case 1:
161 lcd->buf[0] = (data >> 16) & 0xff;
162 lcd->buf[1] = (data >> 8) & 0xff;
163 lcd->buf[2] = data & 0xff;
164 break;
165 case 2:
166 lcd->buf[0] = (data >> 24) & 0xff;
167 lcd->buf[1] = (data >> 16) & 0xff;
168 lcd->buf[2] = (data >> 8) & 0xff;
169 lcd->buf[3] = data & 0xff;
170 break;
171 default:
172 continue;
173 }
174 x->len = nparams + 2;
175 err = spi_sync(lcd->spi_dev, &lcd->msg);
176 if (err)
177 break;
178 }
179
180 return err;
181}
182
183static int tdo24m_adj_mode(struct tdo24m *lcd, int mode)
184{
185 switch (mode) {
186 case MODE_VGA:
187 tdo24m_writes(lcd, lcd_vga_pass_through);
188 tdo24m_writes(lcd, lcd_panel_config);
189 tdo24m_writes(lcd, lcd_vga_transfer);
190 break;
191 case MODE_QVGA:
192 tdo24m_writes(lcd, lcd_qvga_pass_through);
193 tdo24m_writes(lcd, lcd_panel_config);
194 tdo24m_writes(lcd, lcd_qvga_transfer);
195 break;
196 default:
197 return -EINVAL;
198 }
199
200 lcd->mode = mode;
201 return 0;
202}
203
204static int tdo24m_power_on(struct tdo24m *lcd)
205{
206 int err;
207
208 err = tdo24m_writes(lcd, lcd_panel_on);
209 if (err)
210 goto out;
211
212 err = tdo24m_writes(lcd, lcd_panel_reset);
213 if (err)
214 goto out;
215
216 err = tdo24m_adj_mode(lcd, lcd->mode);
217out:
218 return err;
219}
220
221static int tdo24m_power_off(struct tdo24m *lcd)
222{
223 return tdo24m_writes(lcd, lcd_panel_off);
224}
225
226static int tdo24m_power(struct tdo24m *lcd, int power)
227{
228 int ret = 0;
229
230 if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
231 ret = tdo24m_power_on(lcd);
232 else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
233 ret = tdo24m_power_off(lcd);
234
235 if (!ret)
236 lcd->power = power;
237
238 return ret;
239}
240
241
242static int tdo24m_set_power(struct lcd_device *ld, int power)
243{
244 struct tdo24m *lcd = lcd_get_data(ld);
245 return tdo24m_power(lcd, power);
246}
247
248static int tdo24m_get_power(struct lcd_device *ld)
249{
250 struct tdo24m *lcd = lcd_get_data(ld);
251 return lcd->power;
252}
253
254static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m)
255{
256 struct tdo24m *lcd = lcd_get_data(ld);
257 int mode = MODE_QVGA;
258
259 if (m->xres == 640 || m->xres == 480)
260 mode = MODE_VGA;
261
262 if (lcd->mode == mode)
263 return 0;
264
265 return tdo24m_adj_mode(lcd, mode);
266}
267
268static struct lcd_ops tdo24m_ops = {
269 .get_power = tdo24m_get_power,
270 .set_power = tdo24m_set_power,
271 .set_mode = tdo24m_set_mode,
272};
273
274static int __devinit tdo24m_probe(struct spi_device *spi)
275{
276 struct tdo24m *lcd;
277 struct spi_message *m;
278 struct spi_transfer *x;
279 int err;
280
281 spi->bits_per_word = 8;
282 spi->mode = SPI_MODE_3;
283 err = spi_setup(spi);
284 if (err)
285 return err;
286
287 lcd = kzalloc(sizeof(struct tdo24m), GFP_KERNEL);
288 if (!lcd)
289 return -ENOMEM;
290
291 lcd->spi_dev = spi;
292 lcd->power = FB_BLANK_POWERDOWN;
293 lcd->mode = MODE_VGA; /* default to VGA */
294
295 lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL));
296 if (lcd->buf == NULL) {
297 kfree(lcd);
298 return -ENOMEM;
299 }
300
301 m = &lcd->msg;
302 x = &lcd->xfer;
303
304 spi_message_init(m);
305
306 x->tx_buf = &lcd->buf[0];
307 spi_message_add_tail(x, m);
308
309 lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
310 lcd, &tdo24m_ops);
311 if (IS_ERR(lcd->lcd_dev)) {
312 err = PTR_ERR(lcd->lcd_dev);
313 goto out_free;
314 }
315
316 dev_set_drvdata(&spi->dev, lcd);
317 err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
318 if (err)
319 goto out_unregister;
320
321 return 0;
322
323out_unregister:
324 lcd_device_unregister(lcd->lcd_dev);
325out_free:
326 kfree(lcd->buf);
327 kfree(lcd);
328 return err;
329}
330
331static int __devexit tdo24m_remove(struct spi_device *spi)
332{
333 struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
334
335 tdo24m_power(lcd, FB_BLANK_POWERDOWN);
336 lcd_device_unregister(lcd->lcd_dev);
337 kfree(lcd->buf);
338 kfree(lcd);
339
340 return 0;
341}
342
343#ifdef CONFIG_PM
344static int tdo24m_suspend(struct spi_device *spi, pm_message_t state)
345{
346 struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
347
348 return tdo24m_power(lcd, FB_BLANK_POWERDOWN);
349}
350
351static int tdo24m_resume(struct spi_device *spi)
352{
353 struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
354
355 return tdo24m_power(lcd, FB_BLANK_UNBLANK);
356}
357#else
358#define tdo24m_suspend NULL
359#define tdo24m_resume NULL
360#endif
361
362/* Power down all displays on reboot, poweroff or halt */
363static void tdo24m_shutdown(struct spi_device *spi)
364{
365 struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
366
367 tdo24m_power(lcd, FB_BLANK_POWERDOWN);
368}
369
370static struct spi_driver tdo24m_driver = {
371 .driver = {
372 .name = "tdo24m",
373 .owner = THIS_MODULE,
374 },
375 .probe = tdo24m_probe,
376 .remove = __devexit_p(tdo24m_remove),
377 .shutdown = tdo24m_shutdown,
378 .suspend = tdo24m_suspend,
379 .resume = tdo24m_resume,
380};
381
382static int __init tdo24m_init(void)
383{
384 return spi_register_driver(&tdo24m_driver);
385}
386module_init(tdo24m_init);
387
388static void __exit tdo24m_exit(void)
389{
390 spi_unregister_driver(&tdo24m_driver);
391}
392module_exit(tdo24m_exit);
393
394MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
395MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel");
396MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
new file mode 100644
index 000000000000..43edbada12d1
--- /dev/null
+++ b/drivers/video/backlight/tosa_bl.c
@@ -0,0 +1,198 @@
1/*
2 * LCD / Backlight control code for Sharp SL-6000x (tosa)
3 *
4 * Copyright (c) 2005 Dirk Opfer
5 * Copyright (c) 2007,2008 Dmitry Baryshkov
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
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/spi/spi.h>
17#include <linux/i2c.h>
18#include <linux/gpio.h>
19#include <linux/fb.h>
20#include <linux/backlight.h>
21
22#include <asm/mach/sharpsl_param.h>
23
24#include <mach/tosa.h>
25
26#define COMADJ_DEFAULT 97
27
28#define DAC_CH1 0
29#define DAC_CH2 1
30
31struct tosa_bl_data {
32 struct i2c_client *i2c;
33 struct backlight_device *bl;
34
35 int comadj;
36};
37
38static void tosa_bl_set_backlight(struct tosa_bl_data *data, int brightness)
39{
40 struct spi_device *spi = data->i2c->dev.platform_data;
41
42 i2c_smbus_write_byte_data(data->i2c, DAC_CH1, data->comadj);
43
44 /* SetBacklightDuty */
45 i2c_smbus_write_byte_data(data->i2c, DAC_CH2, (u8)(brightness & 0xff));
46
47 /* SetBacklightVR */
48 gpio_set_value(TOSA_GPIO_BL_C20MA, brightness & 0x100);
49
50 tosa_bl_enable(spi, brightness);
51}
52
53static int tosa_bl_update_status(struct backlight_device *dev)
54{
55 struct backlight_properties *props = &dev->props;
56 struct tosa_bl_data *data = dev_get_drvdata(&dev->dev);
57 int power = max(props->power, props->fb_blank);
58 int brightness = props->brightness;
59
60 if (power)
61 brightness = 0;
62
63 tosa_bl_set_backlight(data, brightness);
64
65 return 0;
66}
67
68static int tosa_bl_get_brightness(struct backlight_device *dev)
69{
70 struct backlight_properties *props = &dev->props;
71
72 return props->brightness;
73}
74
75static struct backlight_ops bl_ops = {
76 .get_brightness = tosa_bl_get_brightness,
77 .update_status = tosa_bl_update_status,
78};
79
80static int __devinit tosa_bl_probe(struct i2c_client *client,
81 const struct i2c_device_id *id)
82{
83 struct tosa_bl_data *data = kzalloc(sizeof(struct tosa_bl_data), GFP_KERNEL);
84 int ret = 0;
85 if (!data)
86 return -ENOMEM;
87
88 data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
89
90 ret = gpio_request(TOSA_GPIO_BL_C20MA, "backlight");
91 if (ret) {
92 dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
93 goto err_gpio_bl;
94 }
95 ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
96 if (ret)
97 goto err_gpio_dir;
98
99 i2c_set_clientdata(client, data);
100 data->i2c = client;
101
102 data->bl = backlight_device_register("tosa-bl", &client->dev,
103 data, &bl_ops);
104 if (IS_ERR(data->bl)) {
105 ret = PTR_ERR(data->bl);
106 goto err_reg;
107 }
108
109 data->bl->props.brightness = 69;
110 data->bl->props.max_brightness = 512 - 1;
111 data->bl->props.power = FB_BLANK_UNBLANK;
112
113 backlight_update_status(data->bl);
114
115 return 0;
116
117err_reg:
118 data->bl = NULL;
119 i2c_set_clientdata(client, NULL);
120err_gpio_dir:
121 gpio_free(TOSA_GPIO_BL_C20MA);
122err_gpio_bl:
123 kfree(data);
124 return ret;
125}
126
127static int __devexit tosa_bl_remove(struct i2c_client *client)
128{
129 struct tosa_bl_data *data = i2c_get_clientdata(client);
130
131 backlight_device_unregister(data->bl);
132 data->bl = NULL;
133 i2c_set_clientdata(client, NULL);
134
135 gpio_free(TOSA_GPIO_BL_C20MA);
136
137 kfree(data);
138
139 return 0;
140}
141
142#ifdef CONFIG_PM
143static int tosa_bl_suspend(struct i2c_client *client, pm_message_t pm)
144{
145 struct tosa_bl_data *data = i2c_get_clientdata(client);
146
147 tosa_bl_set_backlight(data, 0);
148
149 return 0;
150}
151
152static int tosa_bl_resume(struct i2c_client *client)
153{
154 struct tosa_bl_data *data = i2c_get_clientdata(client);
155
156 backlight_update_status(data->bl);
157 return 0;
158}
159#else
160#define tosa_bl_suspend NULL
161#define tosa_bl_resume NULL
162#endif
163
164static const struct i2c_device_id tosa_bl_id[] = {
165 { "tosa-bl", 0 },
166 { },
167};
168
169
170static struct i2c_driver tosa_bl_driver = {
171 .driver = {
172 .name = "tosa-bl",
173 .owner = THIS_MODULE,
174 },
175 .probe = tosa_bl_probe,
176 .remove = __devexit_p(tosa_bl_remove),
177 .suspend = tosa_bl_suspend,
178 .resume = tosa_bl_resume,
179 .id_table = tosa_bl_id,
180};
181
182static int __init tosa_bl_init(void)
183{
184 return i2c_add_driver(&tosa_bl_driver);
185}
186
187static void __exit tosa_bl_exit(void)
188{
189 i2c_del_driver(&tosa_bl_driver);
190}
191
192module_init(tosa_bl_init);
193module_exit(tosa_bl_exit);
194
195MODULE_AUTHOR("Dmitry Baryshkov");
196MODULE_LICENSE("GPL v2");
197MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");
198
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
new file mode 100644
index 000000000000..57a26649f1a5
--- /dev/null
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -0,0 +1,280 @@
1/*
2 * LCD / Backlight control code for Sharp SL-6000x (tosa)
3 *
4 * Copyright (c) 2005 Dirk Opfer
5 * Copyright (c) 2007,2008 Dmitry Baryshkov
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
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/spi/spi.h>
17#include <linux/i2c.h>
18#include <linux/gpio.h>
19#include <linux/delay.h>
20#include <linux/lcd.h>
21#include <linux/fb.h>
22
23#include <asm/mach/sharpsl_param.h>
24
25#include <mach/tosa.h>
26
27#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
28
29#define TG_REG0_VQV 0x0001
30#define TG_REG0_COLOR 0x0002
31#define TG_REG0_UD 0x0004
32#define TG_REG0_LR 0x0008
33
34#define DAC_BASE 0x4e
35
36struct tosa_lcd_data {
37 struct spi_device *spi;
38 struct lcd_device *lcd;
39 struct i2c_client *i2c;
40
41 int lcd_power;
42};
43
44static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data)
45{
46 u8 buf[1];
47 struct spi_message msg;
48 struct spi_transfer xfer = {
49 .len = 1,
50 .cs_change = 1,
51 .tx_buf = buf,
52 };
53
54 buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f);
55 spi_message_init(&msg);
56 spi_message_add_tail(&xfer, &msg);
57
58 return spi_sync(spi, &msg);
59}
60
61int tosa_bl_enable(struct spi_device *spi, int enable)
62{
63 /* bl_enable GP04=1 otherwise GP04=0*/
64 return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00);
65}
66EXPORT_SYMBOL(tosa_bl_enable);
67
68static void tosa_lcd_tg_init(struct tosa_lcd_data *data)
69{
70 /* TG on */
71 gpio_set_value(TOSA_GPIO_TG_ON, 0);
72
73 mdelay(60);
74
75 /* delayed 0clk TCTL signal for VGA */
76 tosa_tg_send(data->spi, TG_TPOSCTL, 0x00);
77 /* GPOS0=powercontrol, GPOS1=GPIO, GPOS2=TCTL */
78 tosa_tg_send(data->spi, TG_GPOSR, 0x02);
79}
80
81static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
82{
83 struct spi_device *spi = data->spi;
84 const int value = TG_REG0_COLOR | TG_REG0_UD | TG_REG0_LR;
85 tosa_tg_send(spi, TG_PNLCTL, value | TG_REG0_VQV); /* this depends on mode */
86
87 /* TG LCD pannel power up */
88 tosa_tg_send(spi, TG_PINICTL,0x4);
89 mdelay(50);
90
91 /* TG LCD GVSS */
92 tosa_tg_send(spi, TG_PINICTL,0x0);
93
94 if (!data->i2c) {
95 /* after the pannel is powered up the first time, we can access the i2c bus */
96 /* so probe for the DAC */
97 struct i2c_adapter *adap = i2c_get_adapter(0);
98 struct i2c_board_info info = {
99 .type = "tosa-bl",
100 .addr = DAC_BASE,
101 .platform_data = data->spi,
102 };
103 data->i2c = i2c_new_device(adap, &info);
104 }
105}
106
107static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
108{
109 struct spi_device *spi = data->spi;
110
111 /* TG LCD VHSA off */
112 tosa_tg_send(spi, TG_PINICTL,0x4);
113 mdelay(50);
114
115 /* TG LCD signal off */
116 tosa_tg_send(spi, TG_PINICTL,0x6);
117 mdelay(50);
118
119 /* TG Off */
120 gpio_set_value(TOSA_GPIO_TG_ON, 1);
121 mdelay(100);
122}
123
124int tosa_lcd_set_power(struct lcd_device *lcd, int power)
125{
126 struct tosa_lcd_data *data = lcd_get_data(lcd);
127
128 if (POWER_IS_ON(power) && !POWER_IS_ON(data->lcd_power))
129 tosa_lcd_tg_on(data);
130
131 if (!POWER_IS_ON(power) && POWER_IS_ON(data->lcd_power))
132 tosa_lcd_tg_off(data);
133
134 data->lcd_power = power;
135 return 0;
136}
137
138static int tosa_lcd_get_power(struct lcd_device *lcd)
139{
140 struct tosa_lcd_data *data = lcd_get_data(lcd);
141
142 return data->lcd_power;
143}
144
145static struct lcd_ops tosa_lcd_ops = {
146 .set_power = tosa_lcd_set_power,
147 .get_power = tosa_lcd_get_power,
148};
149
150static int __devinit tosa_lcd_probe(struct spi_device *spi)
151{
152 int ret;
153 struct tosa_lcd_data *data;
154
155 data = kzalloc(sizeof(struct tosa_lcd_data), GFP_KERNEL);
156 if (!data)
157 return -ENOMEM;
158
159 /*
160 * bits_per_word cannot be configured in platform data
161 */
162 spi->bits_per_word = 8;
163
164 ret = spi_setup(spi);
165 if (ret < 0)
166 goto err_spi;
167
168 data->spi = spi;
169 dev_set_drvdata(&spi->dev, data);
170
171 ret = gpio_request(TOSA_GPIO_TG_ON, "tg #pwr");
172 if (ret < 0)
173 goto err_gpio_tg;
174
175 mdelay(60);
176
177 ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0);
178 if (ret < 0)
179 goto err_gpio_dir;
180
181 mdelay(60);
182 tosa_lcd_tg_init(data);
183
184 tosa_lcd_tg_on(data);
185
186 data->lcd = lcd_device_register("tosa-lcd", &spi->dev, data,
187 &tosa_lcd_ops);
188
189 if (IS_ERR(data->lcd)) {
190 ret = PTR_ERR(data->lcd);
191 data->lcd = NULL;
192 goto err_register;
193 }
194
195 return 0;
196
197err_register:
198 tosa_lcd_tg_off(data);
199err_gpio_dir:
200 gpio_free(TOSA_GPIO_TG_ON);
201err_gpio_tg:
202 dev_set_drvdata(&spi->dev, NULL);
203err_spi:
204 kfree(data);
205 return ret;
206}
207
208static int __devexit tosa_lcd_remove(struct spi_device *spi)
209{
210 struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
211
212 lcd_device_unregister(data->lcd);
213
214 if (data->i2c)
215 i2c_unregister_device(data->i2c);
216
217 tosa_lcd_tg_off(data);
218
219 gpio_free(TOSA_GPIO_TG_ON);
220 dev_set_drvdata(&spi->dev, NULL);
221 kfree(data);
222
223 return 0;
224}
225
226#ifdef CONFIG_PM
227static int tosa_lcd_suspend(struct spi_device *spi, pm_message_t state)
228{
229 struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
230
231 tosa_lcd_tg_off(data);
232
233 return 0;
234}
235
236static int tosa_lcd_resume(struct spi_device *spi)
237{
238 struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
239
240 tosa_lcd_tg_init(data);
241 if (POWER_IS_ON(data->lcd_power))
242 tosa_lcd_tg_on(data);
243 else
244 tosa_lcd_tg_off(data);
245
246 return 0;
247}
248#else
249#define tosa_lcd_suspend NULL
250#define tosa_lcd_reume NULL
251#endif
252
253static struct spi_driver tosa_lcd_driver = {
254 .driver = {
255 .name = "tosa-lcd",
256 .owner = THIS_MODULE,
257 },
258 .probe = tosa_lcd_probe,
259 .remove = __devexit_p(tosa_lcd_remove),
260 .suspend = tosa_lcd_suspend,
261 .resume = tosa_lcd_resume,
262};
263
264static int __init tosa_lcd_init(void)
265{
266 return spi_register_driver(&tosa_lcd_driver);
267}
268
269static void __exit tosa_lcd_exit(void)
270{
271 spi_unregister_driver(&tosa_lcd_driver);
272}
273
274module_init(tosa_lcd_init);
275module_exit(tosa_lcd_exit);
276
277MODULE_AUTHOR("Dmitry Baryshkov");
278MODULE_LICENSE("GPL v2");
279MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA");
280
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
new file mode 100644
index 000000000000..593c7687d54a
--- /dev/null
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -0,0 +1,284 @@
1/* drivers/video/backlight/vgg2432a4.c
2 *
3 * VGG2432A4 (ILI9320) LCD controller driver.
4 *
5 * Copyright 2007 Simtec Electronics
6 * http://armlinux.simtec.co.uk/
7 * Ben Dooks <ben@simtec.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/fb.h>
17#include <linux/init.h>
18#include <linux/lcd.h>
19#include <linux/module.h>
20
21#include <linux/spi/spi.h>
22
23#include <video/ili9320.h>
24
25#include "ili9320.h"
26
27/* Device initialisation sequences */
28
29static struct ili9320_reg vgg_init1[] = {
30 {
31 .address = ILI9320_POWER1,
32 .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
33 }, {
34 .address = ILI9320_POWER2,
35 .value = (ILI9320_POWER2_VC(7) |
36 ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)),
37 }, {
38 .address = ILI9320_POWER3,
39 .value = ILI9320_POWER3_VRH(0),
40 }, {
41 .address = ILI9320_POWER4,
42 .value = ILI9320_POWER4_VREOUT(0),
43 },
44};
45
46static struct ili9320_reg vgg_init2[] = {
47 {
48 .address = ILI9320_POWER1,
49 .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
50 ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP),
51 }, {
52 .address = ILI9320_POWER2,
53 .value = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3),
54 }
55};
56
57static struct ili9320_reg vgg_gamma[] = {
58 {
59 .address = ILI9320_GAMMA1,
60 .value = 0x0000,
61 }, {
62 .address = ILI9320_GAMMA2,
63 .value = 0x0505,
64 }, {
65 .address = ILI9320_GAMMA3,
66 .value = 0x0004,
67 }, {
68 .address = ILI9320_GAMMA4,
69 .value = 0x0006,
70 }, {
71 .address = ILI9320_GAMMA5,
72 .value = 0x0707,
73 }, {
74 .address = ILI9320_GAMMA6,
75 .value = 0x0105,
76 }, {
77 .address = ILI9320_GAMMA7,
78 .value = 0x0002,
79 }, {
80 .address = ILI9320_GAMMA8,
81 .value = 0x0707,
82 }, {
83 .address = ILI9320_GAMMA9,
84 .value = 0x0704,
85 }, {
86 .address = ILI9320_GAMMA10,
87 .value = 0x807,
88 }
89
90};
91
92static struct ili9320_reg vgg_init0[] = {
93 [0] = {
94 /* set direction and scan mode gate */
95 .address = ILI9320_DRIVER,
96 .value = ILI9320_DRIVER_SS,
97 }, {
98 .address = ILI9320_DRIVEWAVE,
99 .value = (ILI9320_DRIVEWAVE_MUSTSET |
100 ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC),
101 }, {
102 .address = ILI9320_ENTRYMODE,
103 .value = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
104 }, {
105 .address = ILI9320_RESIZING,
106 .value = 0x0,
107 },
108};
109
110
111static int vgg2432a4_lcd_init(struct ili9320 *lcd,
112 struct ili9320_platdata *cfg)
113{
114 unsigned int addr;
115 int ret;
116
117 /* Set VCore before anything else (VGG243237-6UFLWA) */
118 ret = ili9320_write(lcd, 0x00e5, 0x8000);
119 if (ret)
120 goto err_initial;
121
122 /* Start the oscillator up before we can do anything else. */
123 ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
124 if (ret)
125 goto err_initial;
126
127 /* must wait at-lesat 10ms after starting */
128 mdelay(15);
129
130 ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0));
131 if (ret != 0)
132 goto err_initial;
133
134 ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2);
135 ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3);
136 ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4);
137
138 ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1);
139 ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0);
140 ili9320_write(lcd, ILI9320_RGB_IF2, ILI9320_RGBIF2_DPL);
141
142 ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1));
143 if (ret != 0)
144 goto err_vgg;
145
146 mdelay(300);
147
148 ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2));
149 if (ret != 0)
150 goto err_vgg2;
151
152 mdelay(100);
153
154 ili9320_write(lcd, ILI9320_POWER3, 0x13c);
155
156 mdelay(100);
157
158 ili9320_write(lcd, ILI9320_POWER4, 0x1c00);
159 ili9320_write(lcd, ILI9320_POWER7, 0x000e);
160
161 mdelay(100);
162
163 ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00);
164 ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00);
165
166 ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma));
167 if (ret != 0)
168 goto err_vgg3;
169
170 ili9320_write(lcd, ILI9320_HORIZ_START, 0x0);
171 ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1);
172 ili9320_write(lcd, ILI9320_VERT_START, 0x0);
173 ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1);
174
175 ili9320_write(lcd, ILI9320_DRIVER2,
176 ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D));
177
178 ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1);
179 ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00);
180
181 for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END;
182 addr++) {
183 ili9320_write(lcd, addr, 0x0);
184 }
185
186 ili9320_write(lcd, ILI9320_INTERFACE1, 0x10);
187 ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2);
188 ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3);
189 ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4);
190 ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5);
191 ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6);
192
193 lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE |
194 ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE |
195 0x40);
196
197 ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
198
199 return 0;
200
201 err_vgg3:
202 err_vgg2:
203 err_vgg:
204 err_initial:
205 return ret;
206}
207
208#ifdef CONFIG_PM
209static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state)
210{
211 return ili9320_suspend(dev_get_drvdata(&spi->dev), state);
212}
213
214static int vgg2432a4_resume(struct spi_device *spi)
215{
216 return ili9320_resume(dev_get_drvdata(&spi->dev));
217}
218#else
219#define vgg2432a4_suspend NULL
220#define vgg2432a4_resume NULL
221#endif
222
223static struct ili9320_client vgg2432a4_client = {
224 .name = "VGG2432A4",
225 .init = vgg2432a4_lcd_init,
226};
227
228/* Device probe */
229
230static int __devinit vgg2432a4_probe(struct spi_device *spi)
231{
232 int ret;
233
234 ret = ili9320_probe_spi(spi, &vgg2432a4_client);
235 if (ret != 0) {
236 dev_err(&spi->dev, "failed to initialise ili9320\n");
237 return ret;
238 }
239
240 return 0;
241}
242
243static int __devexit vgg2432a4_remove(struct spi_device *spi)
244{
245 return ili9320_remove(dev_get_drvdata(&spi->dev));
246}
247
248static void vgg2432a4_shutdown(struct spi_device *spi)
249{
250 ili9320_shutdown(dev_get_drvdata(&spi->dev));
251}
252
253static struct spi_driver vgg2432a4_driver = {
254 .driver = {
255 .name = "VGG2432A4",
256 .owner = THIS_MODULE,
257 },
258 .probe = vgg2432a4_probe,
259 .remove = __devexit_p(vgg2432a4_remove),
260 .shutdown = vgg2432a4_shutdown,
261 .suspend = vgg2432a4_suspend,
262 .resume = vgg2432a4_resume,
263};
264
265/* Device driver initialisation */
266
267static int __init vgg2432a4_init(void)
268{
269 return spi_register_driver(&vgg2432a4_driver);
270}
271
272static void __exit vgg2432a4_exit(void)
273{
274 spi_unregister_driver(&vgg2432a4_driver);
275}
276
277module_init(vgg2432a4_init);
278module_exit(vgg2432a4_exit);
279
280MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
281MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
282MODULE_LICENSE("GPL v2");
283
284
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 49834a67a623..7644ed249564 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -58,7 +58,7 @@
58#include <asm/gpio.h> 58#include <asm/gpio.h>
59#include <asm/portmux.h> 59#include <asm/portmux.h>
60 60
61#include <asm/mach/bf54x-lq043.h> 61#include <mach/bf54x-lq043.h>
62 62
63#define NO_BL_SUPPORT 63#define NO_BL_SUPPORT
64 64
@@ -478,7 +478,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
478 return 0; 478 return 0;
479} 479}
480 480
481static int bfin_lcd_check_fb(struct fb_info *fi) 481static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
482{ 482{
483 if (!fi || (fi == &bfin_bf54x_fb)) 483 if (!fi || (fi == &bfin_bf54x_fb))
484 return 1; 484 return 1;
@@ -733,7 +733,6 @@ static int bfin_bf54x_remove(struct platform_device *pdev)
733static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state) 733static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state)
734{ 734{
735 struct fb_info *fbinfo = platform_get_drvdata(pdev); 735 struct fb_info *fbinfo = platform_get_drvdata(pdev);
736 struct bfin_bf54xfb_info *info = fbinfo->par;
737 736
738 bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); 737 bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
739 disable_dma(CH_EPPI0); 738 disable_dma(CH_EPPI0);
@@ -747,8 +746,18 @@ static int bfin_bf54x_resume(struct platform_device *pdev)
747 struct fb_info *fbinfo = platform_get_drvdata(pdev); 746 struct fb_info *fbinfo = platform_get_drvdata(pdev);
748 struct bfin_bf54xfb_info *info = fbinfo->par; 747 struct bfin_bf54xfb_info *info = fbinfo->par;
749 748
750 enable_dma(CH_EPPI0); 749 if (info->lq043_open_cnt) {
751 bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); 750
751 bfin_write_EPPI0_CONTROL(0);
752 SSYNC();
753
754 config_dma(info);
755 config_ppi(info);
756
757 /* start dma */
758 enable_dma(CH_EPPI0);
759 bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
760 }
752 761
753 return 0; 762 return 0;
754} 763}
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 135d6dd7e672..7d1b819e501c 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -396,7 +396,7 @@ static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
396 return 0; 396 return 0;
397} 397}
398 398
399static int bfin_lcd_check_fb(struct fb_info *fi) 399static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
400{ 400{
401 if (!fi || (fi == &bfin_t350mcqb_fb)) 401 if (!fi || (fi == &bfin_t350mcqb_fb))
402 return 1; 402 return 1;
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index e721644bad74..1e35ba6f18e0 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -372,7 +372,7 @@ static int __devexit bw2_remove(struct of_device *op)
372 return 0; 372 return 0;
373} 373}
374 374
375static struct of_device_id bw2_match[] = { 375static const struct of_device_id bw2_match[] = {
376 { 376 {
377 .name = "bwtwo", 377 .name = "bwtwo",
378 }, 378 },
diff --git a/drivers/video/c2p.c b/drivers/video/c2p.c
index 5c30bbd33054..376bc07ff952 100644
--- a/drivers/video/c2p.c
+++ b/drivers/video/c2p.c
@@ -12,6 +12,7 @@
12 * for more details. 12 * for more details.
13 */ 13 */
14 14
15#include <linux/module.h>
15#include <linux/string.h> 16#include <linux/string.h>
16#include "c2p.h" 17#include "c2p.h"
17 18
@@ -226,4 +227,6 @@ void c2p(u8 *dst, const u8 *src, u32 dx, u32 dy, u32 width, u32 height,
226 dst += dst_nextline; 227 dst += dst_nextline;
227 } 228 }
228} 229}
230EXPORT_SYMBOL_GPL(c2p);
229 231
232MODULE_LICENSE("GPL");
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
new file mode 100644
index 000000000000..c9b191319a9a
--- /dev/null
+++ b/drivers/video/carminefb.c
@@ -0,0 +1,790 @@
1/*
2 * Frame buffer driver for the Carmine GPU.
3 *
4 * The driver configures the GPU as follows
5 * - FB0 is display 0 with unique memory area
6 * - FB1 is display 1 with unique memory area
7 * - both display use 32 bit colors
8 */
9#include <linux/delay.h>
10#include <linux/errno.h>
11#include <linux/fb.h>
12#include <linux/interrupt.h>
13#include <linux/pci.h>
14
15#include "carminefb.h"
16#include "carminefb_regs.h"
17
18#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
19#error "The endianness of the target host has not been defined."
20#endif
21
22/*
23 * The initial video mode can be supplied via two different ways:
24 * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
25 * - as an integer that picks the video mode from carmine_modedb[] (module
26 * option fb_mode)
27 *
28 * If nothing is used than the initial video mode will be the
29 * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
30 */
31#define CARMINEFB_DEFAULT_VIDEO_MODE 1
32
33static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
34module_param(fb_mode, uint, 444);
35MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
36
37static char *fb_mode_str;
38module_param(fb_mode_str, charp, 444);
39MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
40
41/*
42 * Carminefb displays:
43 * 0b000 None
44 * 0b001 Display 0
45 * 0b010 Display 1
46 */
47static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
48module_param(fb_displays, int, 444);
49MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
50
51struct carmine_hw {
52 void __iomem *v_regs;
53 void __iomem *screen_mem;
54 struct fb_info *fb[MAX_DISPLAY];
55};
56
57struct carmine_resolution {
58 u32 htp;
59 u32 hsp;
60 u32 hsw;
61 u32 hdp;
62 u32 vtr;
63 u32 vsp;
64 u32 vsw;
65 u32 vdp;
66 u32 disp_mode;
67};
68
69struct carmine_fb {
70 void __iomem *display_reg;
71 void __iomem *screen_base;
72 u32 smem_offset;
73 u32 cur_mode;
74 u32 new_mode;
75 struct carmine_resolution *res;
76 u32 pseudo_palette[16];
77};
78
79static struct fb_fix_screeninfo carminefb_fix __devinitdata = {
80 .id = "Carmine",
81 .type = FB_TYPE_PACKED_PIXELS,
82 .visual = FB_VISUAL_TRUECOLOR,
83 .accel = FB_ACCEL_NONE,
84};
85
86static const struct fb_videomode carmine_modedb[] = {
87 {
88 .name = "640x480",
89 .xres = 640,
90 .yres = 480,
91 }, {
92 .name = "800x600",
93 .xres = 800,
94 .yres = 600,
95 },
96};
97
98static struct carmine_resolution car_modes[] = {
99 {
100 /* 640x480 */
101 .htp = 800,
102 .hsp = 672,
103 .hsw = 96,
104 .hdp = 640,
105 .vtr = 525,
106 .vsp = 490,
107 .vsw = 2,
108 .vdp = 480,
109 .disp_mode = 0x1400,
110 },
111 {
112 /* 800x600 */
113 .htp = 1060,
114 .hsp = 864,
115 .hsw = 72,
116 .hdp = 800,
117 .vtr = 628,
118 .vsp = 601,
119 .vsw = 2,
120 .vdp = 600,
121 .disp_mode = 0x0d00,
122 }
123};
124
125static int carmine_find_mode(const struct fb_var_screeninfo *var)
126{
127 int i;
128
129 for (i = 0; i < ARRAY_SIZE(car_modes); i++)
130 if (car_modes[i].hdp == var->xres &&
131 car_modes[i].vdp == var->yres)
132 return i;
133 return -EINVAL;
134}
135
136static void c_set_disp_reg(const struct carmine_fb *par,
137 u32 offset, u32 val)
138{
139 writel(val, par->display_reg + offset);
140}
141
142static u32 c_get_disp_reg(const struct carmine_fb *par,
143 u32 offset)
144{
145 return readl(par->display_reg + offset);
146}
147
148static void c_set_hw_reg(const struct carmine_hw *hw,
149 u32 offset, u32 val)
150{
151 writel(val, hw->v_regs + offset);
152}
153
154static u32 c_get_hw_reg(const struct carmine_hw *hw,
155 u32 offset)
156{
157 return readl(hw->v_regs + offset);
158}
159
160static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
161 unsigned blue, unsigned transp, struct fb_info *info)
162{
163 if (regno >= 16)
164 return 1;
165
166 red >>= 8;
167 green >>= 8;
168 blue >>= 8;
169 transp >>= 8;
170
171 ((u32 *)info->pseudo_palette)[regno] = be32_to_cpu(transp << 24 |
172 red << 0 | green << 8 | blue << 16);
173 return 0;
174}
175
176static int carmine_check_var(struct fb_var_screeninfo *var,
177 struct fb_info *info)
178{
179 int ret;
180
181 ret = carmine_find_mode(var);
182 if (ret < 0)
183 return ret;
184
185 if (var->grayscale || var->rotate || var->nonstd)
186 return -EINVAL;
187
188 var->xres_virtual = var->xres;
189 var->yres_virtual = var->yres;
190
191 var->bits_per_pixel = 32;
192
193#ifdef __BIG_ENDIAN
194 var->transp.offset = 24;
195 var->red.offset = 0;
196 var->green.offset = 8;
197 var->blue.offset = 16;
198#else
199 var->transp.offset = 24;
200 var->red.offset = 16;
201 var->green.offset = 8;
202 var->blue.offset = 0;
203#endif
204
205 var->red.length = 8;
206 var->green.length = 8;
207 var->blue.length = 8;
208 var->transp.length = 8;
209
210 var->red.msb_right = 0;
211 var->green.msb_right = 0;
212 var->blue.msb_right = 0;
213 var->transp.msb_right = 0;
214 return 0;
215}
216
217static void carmine_init_display_param(struct carmine_fb *par)
218{
219 u32 width;
220 u32 height;
221 u32 param;
222 u32 window_size;
223 u32 soffset = par->smem_offset;
224
225 c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
226 c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
227 c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
228 CARMINE_CURSOR0_PRIORITY_MASK |
229 CARMINE_CURSOR1_PRIORITY_MASK |
230 CARMINE_CURSOR_CUTZ_MASK);
231
232 /* Set default cursor position */
233 c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
234 c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
235
236 /* Set default display mode */
237 c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
238 CARMINE_EXT_CMODE_DIRECT24_RGBA);
239 c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
240 CARMINE_EXT_CMODE_DIRECT24_RGBA);
241 c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
242 CARMINE_EXT_CMODE_DIRECT24_RGBA);
243 c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
244 CARMINE_EXT_CMODE_DIRECT24_RGBA);
245 c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
246 CARMINE_EXT_CMODE_DIRECT24_RGBA);
247 c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
248 CARMINE_EXT_CMODE_DIRECT24_RGBA);
249 c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
250 CARMINE_EXT_CMODE_DIRECT24_RGBA);
251 c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
252 CARMINE_EXT_CMODE_DIRECT24_RGBA);
253
254 /* Set default frame size to layer mode register */
255 width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
256 width = width << CARMINE_DISP_WIDTH_SHIFT;
257
258 height = par->res->vdp - 1;
259 param = width | height;
260
261 c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
262 c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
263 c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
264 c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
265 c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
266 c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
267 c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
268 c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
269
270 /* Set default pos and size */
271 window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
272 window_size |= par->res->hdp;
273
274 c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
275 c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
276 c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
277 c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
278 c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
279 c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
280 c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
281 c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
282 c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
283 c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
284 c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
285 c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
286 c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
287 c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
288 c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
289 c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
290
291 /* Set default origin address */
292 c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
293 c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
294 c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
295 c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
296 c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
297 c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
298 c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
299 c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
300
301 /* Set default display address */
302 c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
303 c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
304 c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
305 c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
306 c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
307 c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
308 c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
309
310 /* Set default display position */
311 c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
312 c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
313 c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
314 c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
315 c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
316 c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
317 c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
318
319 /* Set default blend mode */
320 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
321 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
322 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
323 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
324 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
325 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
326 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
327 c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
328
329 /* default transparency mode */
330 c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
331 c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
332 c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
333 c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
334 c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
335 c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
336 c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
337 c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
338
339 /* Set default read skip parameter */
340 c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
341 c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
342 c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
343 c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
344 c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
345 c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
346 c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
347
348 c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
349 c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
350 c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
351 c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
352 c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
353 c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
354 c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
355
356 c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
357 c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
358 c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
359 c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
360 c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
361 c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
362 c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
363}
364
365static void set_display_parameters(struct carmine_fb *par)
366{
367 u32 mode;
368 u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
369
370 /*
371 * display timing. Parameters are decreased by one because hardware
372 * spec is 0 to (n - 1)
373 * */
374 hdp = par->res->hdp - 1;
375 vdp = par->res->vdp - 1;
376 htp = par->res->htp - 1;
377 hsp = par->res->hsp - 1;
378 hsw = par->res->hsw - 1;
379 vtr = par->res->vtr - 1;
380 vsp = par->res->vsp - 1;
381 vsw = par->res->vsw - 1;
382
383 c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
384 htp << CARMINE_DISP_HTP_SHIFT);
385 c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
386 (hdp << CARMINE_DISP_HDB_SHIFT) | hdp);
387 c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
388 (vsw << CARMINE_DISP_VSW_SHIFT) |
389 (hsw << CARMINE_DISP_HSW_SHIFT) |
390 (hsp));
391 c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
392 vtr << CARMINE_DISP_VTR_SHIFT);
393 c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
394 (vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
395
396 /* clock */
397 mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
398 mode = (mode & ~CARMINE_DISP_DCM_MASK) |
399 (par->res->disp_mode & CARMINE_DISP_DCM_MASK);
400 /* enable video output and layer 0 */
401 mode |= CARMINE_DEN | CARMINE_L0E;
402 c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
403}
404
405static int carmine_set_par(struct fb_info *info)
406{
407 struct carmine_fb *par = info->par;
408 int ret;
409
410 ret = carmine_find_mode(&info->var);
411 if (ret < 0)
412 return ret;
413
414 par->new_mode = ret;
415 if (par->cur_mode != par->new_mode) {
416
417 par->cur_mode = par->new_mode;
418 par->res = &car_modes[par->new_mode];
419
420 carmine_init_display_param(par);
421 set_display_parameters(par);
422 }
423
424 info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
425 return 0;
426}
427
428static int init_hardware(struct carmine_hw *hw)
429{
430 u32 flags;
431 u32 loops;
432 u32 ret;
433
434 /* Initalize Carmine */
435 /* Sets internal clock */
436 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
437 CARMINE_DFLT_IP_CLOCK_ENABLE);
438
439 /* Video signal output is turned off */
440 c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
441 c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
442
443 /* Software reset */
444 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
445 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
446
447 /* I/O mode settings */
448 flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
449 CARMINE_DFLT_IP_DCTL_IO_CONT0;
450 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
451 flags);
452
453 /* DRAM initial sequence */
454 flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
455 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
456 flags);
457
458 flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
459 CARMINE_DFLT_IP_DCTL_EMODE;
460 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
461 flags);
462
463 flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
464 CARMINE_DFLT_IP_DCTL_SET_TIME2;
465 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
466 flags);
467
468 flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
469 CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
470 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
471
472 flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
473 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
474 flags);
475
476 flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
477 CARMINE_DFLT_IP_DCTL_STATES;
478 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
479 flags);
480
481 /* Executes DLL reset */
482 if (CARMINE_DCTL_DLL_RESET) {
483 for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
484
485 ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
486 CARMINE_DCTL_REG_RSV0_STATES);
487 ret &= CARMINE_DCTL_REG_STATES_MASK;
488 if (!ret)
489 break;
490
491 mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
492 }
493
494 if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
495 printk(KERN_ERR "DRAM init failed\n");
496 return -EIO;
497 }
498 }
499
500 flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
501 CARMINE_DFLT_IP_DCTL_ADD;
502 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
503
504 flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
505 CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
506 c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
507 flags);
508
509 /* Initialize the write back register */
510 c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
511 CARMINE_WB_REG_WBM_DEFAULT);
512
513 /* Initialize the Kottos registers */
514 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
515 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
516
517 /* Set DC offsets */
518 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
519 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
520 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
521 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
522 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
523 c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
524 return 0;
525}
526
527static struct fb_ops carminefb_ops = {
528 .owner = THIS_MODULE,
529 .fb_fillrect = cfb_fillrect,
530 .fb_copyarea = cfb_copyarea,
531 .fb_imageblit = cfb_imageblit,
532
533 .fb_check_var = carmine_check_var,
534 .fb_set_par = carmine_set_par,
535 .fb_setcolreg = carmine_setcolreg,
536};
537
538static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
539 int smem_offset, struct device *device, struct fb_info **rinfo)
540{
541 int ret;
542 struct fb_info *info;
543 struct carmine_fb *par;
544
545 info = framebuffer_alloc(sizeof *par, device);
546 if (!info)
547 return -ENOMEM;
548
549 par = info->par;
550 par->display_reg = regs;
551 par->smem_offset = smem_offset;
552
553 info->screen_base = smem_base + smem_offset;
554 info->screen_size = CARMINE_DISPLAY_MEM;
555 info->fbops = &carminefb_ops;
556
557 info->fix = carminefb_fix;
558 info->pseudo_palette = par->pseudo_palette;
559 info->flags = FBINFO_DEFAULT;
560
561 ret = fb_alloc_cmap(&info->cmap, 256, 1);
562 if (ret < 0)
563 goto err_free_fb;
564
565 if (fb_mode > ARRAY_SIZE(carmine_modedb))
566 fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
567
568 par->cur_mode = par->new_mode = ~0;
569
570 ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
571 ARRAY_SIZE(carmine_modedb),
572 &carmine_modedb[fb_mode], 32);
573 if (!ret || ret == 4) {
574 ret = -EINVAL;
575 goto err_dealloc_cmap;
576 }
577
578 fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
579 &info->modelist);
580
581 ret = register_framebuffer(info);
582 if (ret < 0)
583 goto err_dealloc_cmap;
584
585 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
586 info->fix.id);
587
588 *rinfo = info;
589 return 0;
590
591err_dealloc_cmap:
592 fb_dealloc_cmap(&info->cmap);
593err_free_fb:
594 framebuffer_release(info);
595 return ret;
596}
597
598static void cleanup_fb_device(struct fb_info *info)
599{
600 if (info) {
601 unregister_framebuffer(info);
602 fb_dealloc_cmap(&info->cmap);
603 framebuffer_release(info);
604 }
605}
606
607static int __devinit carminefb_probe(struct pci_dev *dev,
608 const struct pci_device_id *ent)
609{
610 struct carmine_hw *hw;
611 struct device *device = &dev->dev;
612 struct fb_info *info;
613 int ret;
614
615 ret = pci_enable_device(dev);
616 if (ret)
617 return ret;
618
619 ret = -ENOMEM;
620 hw = kzalloc(sizeof *hw, GFP_KERNEL);
621 if (!hw)
622 goto err_enable_pci;
623
624 carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
625 carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
626
627 if (!request_mem_region(carminefb_fix.mmio_start,
628 carminefb_fix.mmio_len,
629 "carminefb regbase")) {
630 printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
631 ret = -EBUSY;
632 goto err_free_hw;
633 }
634 hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start,
635 carminefb_fix.mmio_len);
636 if (!hw->v_regs) {
637 printk(KERN_ERR "carminefb: Can't remap %s register.\n",
638 carminefb_fix.id);
639 goto err_free_reg_mmio;
640 }
641
642 carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
643 carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
644
645 /* The memory area tends to be very large (256 MiB). Remap only what
646 * is required for that largest resolution to avoid remaps at run
647 * time
648 */
649 if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
650 carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
651
652 else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
653 printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
654 "are required.", carminefb_fix.smem_len,
655 CARMINE_TOTAL_DIPLAY_MEM);
656 goto err_free_reg_mmio;
657 }
658
659 if (!request_mem_region(carminefb_fix.smem_start,
660 carminefb_fix.smem_len, "carminefb smem")) {
661 printk(KERN_ERR "carminefb: Can't reserve smem.\n");
662 goto err_unmap_vregs;
663 }
664
665 hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start,
666 carminefb_fix.smem_len);
667 if (!hw->screen_mem) {
668 printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
669 release_mem_region(carminefb_fix.smem_start,
670 carminefb_fix.smem_len);
671 goto err_reg_smem;
672 }
673
674 ret = init_hardware(hw);
675 if (ret)
676 goto err_unmap_screen;
677
678 info = NULL;
679 if (fb_displays & CARMINE_USE_DISPLAY0) {
680 ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
681 hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
682 device, &info);
683 if (ret)
684 goto err_deinit_hw;
685 }
686
687 hw->fb[0] = info;
688
689 info = NULL;
690 if (fb_displays & CARMINE_USE_DISPLAY1) {
691 ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
692 hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
693 device, &info);
694 if (ret)
695 goto err_cleanup_fb0;
696 }
697
698 hw->fb[1] = info;
699 info = NULL;
700
701 pci_set_drvdata(dev, hw);
702 return 0;
703
704err_cleanup_fb0:
705 cleanup_fb_device(hw->fb[0]);
706err_deinit_hw:
707 /* disable clock, etc */
708 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
709err_unmap_screen:
710 iounmap(hw->screen_mem);
711err_reg_smem:
712 release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
713err_unmap_vregs:
714 iounmap(hw->v_regs);
715err_free_reg_mmio:
716 release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
717err_free_hw:
718 kfree(hw);
719err_enable_pci:
720 pci_disable_device(dev);
721 return ret;
722}
723
724static void __devexit carminefb_remove(struct pci_dev *dev)
725{
726 struct carmine_hw *hw = pci_get_drvdata(dev);
727 struct fb_fix_screeninfo fix;
728 int i;
729
730 /* in case we use only fb1 and not fb1 */
731 if (hw->fb[0])
732 fix = hw->fb[0]->fix;
733 else
734 fix = hw->fb[1]->fix;
735
736 /* deactivate display(s) and switch clocks */
737 c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
738 c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
739 c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
740
741 for (i = 0; i < MAX_DISPLAY; i++)
742 cleanup_fb_device(hw->fb[i]);
743
744 iounmap(hw->screen_mem);
745 release_mem_region(fix.smem_start, fix.smem_len);
746 iounmap(hw->v_regs);
747 release_mem_region(fix.mmio_start, fix.mmio_len);
748
749 pci_set_drvdata(dev, NULL);
750 pci_disable_device(dev);
751 kfree(hw);
752}
753
754#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
755static struct pci_device_id carmine_devices[] __devinitdata = {
756{
757 PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
758 {0, 0, 0, 0, 0, 0, 0}
759};
760
761MODULE_DEVICE_TABLE(pci, carmine_devices);
762
763static struct pci_driver carmine_pci_driver = {
764 .name = "carminefb",
765 .id_table = carmine_devices,
766 .probe = carminefb_probe,
767 .remove = __devexit_p(carminefb_remove),
768};
769
770static int __init carminefb_init(void)
771{
772 if (!(fb_displays &
773 (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
774 printk(KERN_ERR "If you disable both displays than you don't "
775 "need the driver at all\n");
776 return -EINVAL;
777 }
778 return pci_register_driver(&carmine_pci_driver);
779}
780module_init(carminefb_init);
781
782static void __exit carminefb_cleanup(void)
783{
784 pci_unregister_driver(&carmine_pci_driver);
785}
786module_exit(carminefb_cleanup);
787
788MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
789MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
790MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/carminefb.h b/drivers/video/carminefb.h
new file mode 100644
index 000000000000..05306de0c6b6
--- /dev/null
+++ b/drivers/video/carminefb.h
@@ -0,0 +1,64 @@
1#ifndef CARMINE_CARMINE_H
2#define CARMINE_CARMINE_H
3
4#define CARMINE_MEMORY_BAR 2
5#define CARMINE_CONFIG_BAR 3
6
7#define MAX_DISPLAY 2
8#define CARMINE_DISPLAY_MEM (800 * 600 * 4)
9#define CARMINE_TOTAL_DIPLAY_MEM (CARMINE_DISPLAY_MEM * MAX_DISPLAY)
10
11#define CARMINE_USE_DISPLAY0 (1 << 0)
12#define CARMINE_USE_DISPLAY1 (1 << 1)
13
14/*
15 * This values work on the eval card. Custom boards may use different timings,
16 * here an example :)
17 */
18
19/* DRAM initialization values */
20#ifdef CONFIG_FB_CARMINE_DRAM_EVAL
21
22#define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff)
23#define CARMINE_DFLT_IP_DCTL_ADD (0x05c3)
24#define CARMINE_DFLT_IP_DCTL_MODE (0x0121)
25#define CARMINE_DFLT_IP_DCTL_EMODE (0x8000)
26#define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x4749)
27#define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x2a22)
28#define CARMINE_DFLT_IP_DCTL_REFRESH (0x0042)
29#define CARMINE_DFLT_IP_DCTL_STATES (0x0003)
30#define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020)
31#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f)
32#define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000)
33#define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x6646)
34#define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x0055)
35#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0021)
36#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002)
37#define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555)
38#define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555)
39#define CARMINE_DCTL_DLL_RESET (1)
40#endif
41
42#ifdef CONFIG_CARMINE_DRAM_CUSTOM
43
44#define CARMINE_DFLT_IP_CLOCK_ENABLE (0x03ff)
45#define CARMINE_DFLT_IP_DCTL_ADD (0x03b2)
46#define CARMINE_DFLT_IP_DCTL_MODE (0x0161)
47#define CARMINE_DFLT_IP_DCTL_EMODE (0x8000)
48#define CARMINE_DFLT_IP_DCTL_SET_TIME1 (0x2628)
49#define CARMINE_DFLT_IP_DCTL_SET_TIME2 (0x1a09)
50#define CARMINE_DFLT_IP_DCTL_REFRESH (0x00fe)
51#define CARMINE_DFLT_IP_DCTL_STATES (0x0003)
52#define CARMINE_DFLT_IP_DCTL_RESERVE0 (0x0020)
53#define CARMINE_DFLT_IP_DCTL_FIFO_DEPTH (0x000f)
54#define CARMINE_DFLT_IP_DCTL_RESERVE2 (0x0000)
55#define CARMINE_DFLT_IP_DCTL_DDRIF1 (0x0646)
56#define CARMINE_DFLT_IP_DCTL_DDRIF2 (0x55aa)
57#define CARMINE_DFLT_IP_DCTL_MODE_AFT_RST (0x0061)
58#define CARMINE_DFLT_IP_DCTL_STATES_AFT_RST (0x0002)
59#define CARMINE_DFLT_IP_DCTL_IO_CONT0 (0x0555)
60#define CARMINE_DFLT_IP_DCTL_IO_CONT1 (0x0555)
61#define CARMINE_DCTL_DLL_RESET (1)
62#endif
63
64#endif
diff --git a/drivers/video/carminefb_regs.h b/drivers/video/carminefb_regs.h
new file mode 100644
index 000000000000..045215600b73
--- /dev/null
+++ b/drivers/video/carminefb_regs.h
@@ -0,0 +1,159 @@
1#ifndef _CARMINEFB_REGS_H
2#define _CARMINEFB_REGS_H
3
4#define CARMINE_OVERLAY_EXT_MODE (0x00000002)
5#define CARMINE_GRAPH_REG (0x00000000)
6#define CARMINE_DISP0_REG (0x00100000)
7#define CARMINE_DISP1_REG (0x00140000)
8#define CARMINE_WB_REG (0x00180000)
9#define CARMINE_DCTL_REG (0x00300000)
10#define CARMINE_CTL_REG (0x00400000)
11#define CARMINE_WINDOW_MODE (0x00000001)
12#define CARMINE_EXTEND_MODE (CARMINE_WINDOW_MODE | \
13 CARMINE_OVERLAY_EXT_MODE)
14#define CARMINE_L0E (1 << 16)
15#define CARMINE_L2E (1 << 18)
16#define CARMINE_DEN (1 << 31)
17
18#define CARMINE_EXT_CMODE_DIRECT24_RGBA (0xC0000000)
19#define CARMINE_DCTL_REG_MODE_ADD (0x00)
20#define CARMINE_DCTL_REG_SETTIME1_EMODE (0x04)
21#define CARMINE_DCTL_REG_REFRESH_SETTIME2 (0x08)
22#define CARMINE_DCTL_REG_RSV0_STATES (0x0C)
23#define CARMINE_DCTL_REG_RSV2_RSV1 (0x10)
24#define CARMINE_DCTL_REG_DDRIF2_DDRIF1 (0x14)
25#define CARMINE_DCTL_REG_IOCONT1_IOCONT0 (0x24)
26#define CARMINE_DCTL_REG_STATES_MASK (0x000F)
27#define CARMINE_DCTL_INIT_WAIT_INTERVAL (1)
28#define CARMINE_DCTL_INIT_WAIT_LIMIT (5000)
29#define CARMINE_WB_REG_WBM_DEFAULT (0x0001c020)
30#define CARMINE_DISP_REG_L0RM (0x1880)
31#define CARMINE_DISP_REG_L0PX (0x1884)
32#define CARMINE_DISP_REG_L0PY (0x1888)
33#define CARMINE_DISP_REG_L2RM (0x18A0)
34#define CARMINE_DISP_REG_L2PX (0x18A4)
35#define CARMINE_DISP_REG_L2PY (0x18A8)
36#define CARMINE_DISP_REG_L3RM (0x18B0)
37#define CARMINE_DISP_REG_L3PX (0x18B4)
38#define CARMINE_DISP_REG_L3PY (0x18B8)
39#define CARMINE_DISP_REG_L4RM (0x18C0)
40#define CARMINE_DISP_REG_L4PX (0x18C4)
41#define CARMINE_DISP_REG_L4PY (0x18C8)
42#define CARMINE_DISP_REG_L5RM (0x18D0)
43#define CARMINE_DISP_REG_L5PX (0x18D4)
44#define CARMINE_DISP_REG_L5PY (0x18D8)
45#define CARMINE_DISP_REG_L6RM (0x1924)
46#define CARMINE_DISP_REG_L6PX (0x1928)
47#define CARMINE_DISP_REG_L6PY (0x192C)
48#define CARMINE_DISP_REG_L7RM (0x1964)
49#define CARMINE_DISP_REG_L7PX (0x1968)
50#define CARMINE_DISP_REG_L7PY (0x196C)
51#define CARMINE_WB_REG_WBM (0x0004)
52#define CARMINE_DISP_HTP_SHIFT (16)
53#define CARMINE_DISP_HDB_SHIFT (16)
54#define CARMINE_DISP_HSW_SHIFT (16)
55#define CARMINE_DISP_VSW_SHIFT (24)
56#define CARMINE_DISP_VTR_SHIFT (16)
57#define CARMINE_DISP_VDP_SHIFT (16)
58#define CARMINE_CURSOR_CUTZ_MASK (0x00000100)
59#define CARMINE_CURSOR0_PRIORITY_MASK (0x00010000)
60#define CARMINE_CURSOR1_PRIORITY_MASK (0x00020000)
61#define CARMINE_DISP_WIDTH_SHIFT (16)
62#define CARMINE_DISP_WIN_H_SHIFT (16)
63#define CARMINE_DISP_REG_H_TOTAL (0x0004)
64#define CARMINE_DISP_REG_H_PERIOD (0x0008)
65#define CARMINE_DISP_REG_V_H_W_H_POS (0x000C)
66#define CARMINE_DISP_REG_V_TOTAL (0x0010)
67#define CARMINE_DISP_REG_V_PERIOD_POS (0x0014)
68#define CARMINE_DISP_REG_L0_MODE_W_H (0x0020)
69#define CARMINE_DISP_REG_L0_ORG_ADR (0x0024)
70#define CARMINE_DISP_REG_L0_DISP_ADR (0x0028)
71#define CARMINE_DISP_REG_L0_DISP_POS (0x002C)
72#define CARMINE_DISP_REG_L1_WIDTH (0x0030)
73#define CARMINE_DISP_REG_L1_ORG_ADR (0x0034)
74#define CARMINE_DISP_REG_L2_MODE_W_H (0x0040)
75#define CARMINE_DISP_REG_L2_ORG_ADR1 (0x0044)
76#define CARMINE_DISP_REG_L2_DISP_ADR1 (0x0048)
77#define CARMINE_DISP_REG_L2_DISP_POS (0x0054)
78#define CARMINE_DISP_REG_L3_MODE_W_H (0x0058)
79#define CARMINE_DISP_REG_L3_ORG_ADR1 (0x005C)
80#define CARMINE_DISP_REG_L3_DISP_ADR1 (0x0060)
81#define CARMINE_DISP_REG_L3_DISP_POS (0x006C)
82#define CARMINE_DISP_REG_L4_MODE_W_H (0x0070)
83#define CARMINE_DISP_REG_L4_ORG_ADR1 (0x0074)
84#define CARMINE_DISP_REG_L4_DISP_ADR1 (0x0078)
85#define CARMINE_DISP_REG_L4_DISP_POS (0x0084)
86#define CARMINE_DISP_REG_L5_MODE_W_H (0x0088)
87#define CARMINE_DISP_REG_L5_ORG_ADR1 (0x008C)
88#define CARMINE_DISP_REG_L5_DISP_ADR1 (0x0090)
89#define CARMINE_DISP_REG_L5_DISP_POS (0x009C)
90#define CARMINE_DISP_REG_CURSOR_MODE (0x00A0)
91#define CARMINE_DISP_REG_CUR1_POS (0x00A8)
92#define CARMINE_DISP_REG_CUR2_POS (0x00B0)
93#define CARMINE_DISP_REG_C_TRANS (0x00BC)
94#define CARMINE_DISP_REG_MLMR_TRANS (0x00C0)
95#define CARMINE_DISP_REG_L0_EXT_MODE (0x0110)
96#define CARMINE_DISP_REG_L0_WIN_POS (0x0114)
97#define CARMINE_DISP_REG_L0_WIN_SIZE (0x0118)
98#define CARMINE_DISP_REG_L1_EXT_MODE (0x0120)
99#define CARMINE_DISP_REG_L1_WIN_POS (0x0124)
100#define CARMINE_DISP_REG_L1_WIN_SIZE (0x0128)
101#define CARMINE_DISP_REG_L2_EXT_MODE (0x0130)
102#define CARMINE_DISP_REG_L2_WIN_POS (0x0134)
103#define CARMINE_DISP_REG_L2_WIN_SIZE (0x0138)
104#define CARMINE_DISP_REG_L3_EXT_MODE (0x0140)
105#define CARMINE_DISP_REG_L3_WIN_POS (0x0144)
106#define CARMINE_DISP_REG_L3_WIN_SIZE (0x0148)
107#define CARMINE_DISP_REG_L4_EXT_MODE (0x0150)
108#define CARMINE_DISP_REG_L4_WIN_POS (0x0154)
109#define CARMINE_DISP_REG_L4_WIN_SIZE (0x0158)
110#define CARMINE_DISP_REG_L5_EXT_MODE (0x0160)
111#define CARMINE_DISP_REG_L5_WIN_POS (0x0164)
112#define CARMINE_DISP_REG_L5_WIN_SIZE (0x0168)
113#define CARMINE_DISP_REG_L6_EXT_MODE (0x1918)
114#define CARMINE_DISP_REG_L6_WIN_POS (0x191c)
115#define CARMINE_DISP_REG_L6_WIN_SIZE (0x1920)
116#define CARMINE_DISP_REG_L7_EXT_MODE (0x1958)
117#define CARMINE_DISP_REG_L7_WIN_POS (0x195c)
118#define CARMINE_DISP_REG_L7_WIN_SIZE (0x1960)
119#define CARMINE_DISP_REG_BLEND_MODE_L0 (0x00B4)
120#define CARMINE_DISP_REG_BLEND_MODE_L1 (0x0188)
121#define CARMINE_DISP_REG_BLEND_MODE_L2 (0x018C)
122#define CARMINE_DISP_REG_BLEND_MODE_L3 (0x0190)
123#define CARMINE_DISP_REG_BLEND_MODE_L4 (0x0194)
124#define CARMINE_DISP_REG_BLEND_MODE_L5 (0x0198)
125#define CARMINE_DISP_REG_BLEND_MODE_L6 (0x1990)
126#define CARMINE_DISP_REG_BLEND_MODE_L7 (0x1994)
127#define CARMINE_DISP_REG_L0_TRANS (0x01A0)
128#define CARMINE_DISP_REG_L1_TRANS (0x01A4)
129#define CARMINE_DISP_REG_L2_TRANS (0x01A8)
130#define CARMINE_DISP_REG_L3_TRANS (0x01AC)
131#define CARMINE_DISP_REG_L4_TRANS (0x01B0)
132#define CARMINE_DISP_REG_L5_TRANS (0x01B4)
133#define CARMINE_DISP_REG_L6_TRANS (0x1998)
134#define CARMINE_DISP_REG_L7_TRANS (0x199c)
135#define CARMINE_EXTEND_MODE_MASK (0x00000003)
136#define CARMINE_DISP_DCM_MASK (0x0000FFFF)
137#define CARMINE_DISP_REG_DCM1 (0x0100)
138#define CARMINE_DISP_WIDTH_UNIT (64)
139#define CARMINE_DISP_REG_L6_MODE_W_H (0x1900)
140#define CARMINE_DISP_REG_L6_ORG_ADR1 (0x1904)
141#define CARMINE_DISP_REG_L6_DISP_ADR0 (0x1908)
142#define CARMINE_DISP_REG_L6_DISP_POS (0x1914)
143#define CARMINE_DISP_REG_L7_MODE_W_H (0x1940)
144#define CARMINE_DISP_REG_L7_ORG_ADR1 (0x1944)
145#define CARMINE_DISP_REG_L7_DISP_ADR0 (0x1948)
146#define CARMINE_DISP_REG_L7_DISP_POS (0x1954)
147#define CARMINE_CTL_REG_CLOCK_ENABLE (0x000C)
148#define CARMINE_CTL_REG_SOFTWARE_RESET (0x0010)
149#define CARMINE_CTL_REG_IST_MASK_ALL (0x07FFFFFF)
150#define CARMINE_GRAPH_REG_VRINTM (0x00028064)
151#define CARMINE_GRAPH_REG_VRERRM (0x0002806C)
152#define CARMINE_GRAPH_REG_DC_OFFSET_PX (0x0004005C)
153#define CARMINE_GRAPH_REG_DC_OFFSET_PY (0x00040060)
154#define CARMINE_GRAPH_REG_DC_OFFSET_LX (0x00040064)
155#define CARMINE_GRAPH_REG_DC_OFFSET_LY (0x00040068)
156#define CARMINE_GRAPH_REG_DC_OFFSET_TX (0x0004006C)
157#define CARMINE_GRAPH_REG_DC_OFFSET_TY (0x00040070)
158
159#endif
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index b17e74671779..a2d1882791a5 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -589,7 +589,7 @@ static int __devexit cg14_remove(struct of_device *op)
589 return 0; 589 return 0;
590} 590}
591 591
592static struct of_device_id cg14_match[] = { 592static const struct of_device_id cg14_match[] = {
593 { 593 {
594 .name = "cgfourteen", 594 .name = "cgfourteen",
595 }, 595 },
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 3aa7b6cb0268..99f87fb61d05 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -456,7 +456,7 @@ static int __devexit cg3_remove(struct of_device *op)
456 return 0; 456 return 0;
457} 457}
458 458
459static struct of_device_id cg3_match[] = { 459static const struct of_device_id cg3_match[] = {
460 { 460 {
461 .name = "cgthree", 461 .name = "cgthree",
462 }, 462 },
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 2f64bb3bd254..940ec04f0f1b 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -34,10 +34,11 @@ static int cg6_blank(int, struct fb_info *);
34 34
35static void cg6_imageblit(struct fb_info *, const struct fb_image *); 35static void cg6_imageblit(struct fb_info *, const struct fb_image *);
36static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); 36static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
37static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
37static int cg6_sync(struct fb_info *); 38static int cg6_sync(struct fb_info *);
38static int cg6_mmap(struct fb_info *, struct vm_area_struct *); 39static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
39static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); 40static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
40static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); 41static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
41 42
42/* 43/*
43 * Frame buffer operations 44 * Frame buffer operations
@@ -47,6 +48,7 @@ static struct fb_ops cg6_ops = {
47 .owner = THIS_MODULE, 48 .owner = THIS_MODULE,
48 .fb_setcolreg = cg6_setcolreg, 49 .fb_setcolreg = cg6_setcolreg,
49 .fb_blank = cg6_blank, 50 .fb_blank = cg6_blank,
51 .fb_pan_display = cg6_pan_display,
50 .fb_fillrect = cg6_fillrect, 52 .fb_fillrect = cg6_fillrect,
51 .fb_copyarea = cg6_copyarea, 53 .fb_copyarea = cg6_copyarea,
52 .fb_imageblit = cg6_imageblit, 54 .fb_imageblit = cg6_imageblit,
@@ -161,6 +163,7 @@ static struct fb_ops cg6_ops = {
161#define CG6_THC_MISC_INT_ENAB (1 << 5) 163#define CG6_THC_MISC_INT_ENAB (1 << 5)
162#define CG6_THC_MISC_INT (1 << 4) 164#define CG6_THC_MISC_INT (1 << 4)
163#define CG6_THC_MISC_INIT 0x9f 165#define CG6_THC_MISC_INIT 0x9f
166#define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16))
164 167
165/* The contents are unknown */ 168/* The contents are unknown */
166struct cg6_tec { 169struct cg6_tec {
@@ -280,6 +283,33 @@ static int cg6_sync(struct fb_info *info)
280 return 0; 283 return 0;
281} 284}
282 285
286static void cg6_switch_from_graph(struct cg6_par *par)
287{
288 struct cg6_thc __iomem *thc = par->thc;
289 unsigned long flags;
290
291 spin_lock_irqsave(&par->lock, flags);
292
293 /* Hide the cursor. */
294 sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
295
296 spin_unlock_irqrestore(&par->lock, flags);
297}
298
299static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
300{
301 struct cg6_par *par = (struct cg6_par *)info->par;
302
303 /* We just use this to catch switches out of
304 * graphics mode.
305 */
306 cg6_switch_from_graph(par);
307
308 if (var->xoffset || var->yoffset || var->vmode)
309 return -EINVAL;
310 return 0;
311}
312
283/** 313/**
284 * cg6_fillrect - Draws a rectangle on the screen. 314 * cg6_fillrect - Draws a rectangle on the screen.
285 * 315 *
@@ -643,9 +673,13 @@ static void __devinit cg6_chip_init(struct fb_info *info)
643 struct cg6_par *par = (struct cg6_par *)info->par; 673 struct cg6_par *par = (struct cg6_par *)info->par;
644 struct cg6_tec __iomem *tec = par->tec; 674 struct cg6_tec __iomem *tec = par->tec;
645 struct cg6_fbc __iomem *fbc = par->fbc; 675 struct cg6_fbc __iomem *fbc = par->fbc;
676 struct cg6_thc __iomem *thc = par->thc;
646 u32 rev, conf, mode; 677 u32 rev, conf, mode;
647 int i; 678 int i;
648 679
680 /* Hide the cursor. */
681 sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
682
649 /* Turn off stuff in the Transform Engine. */ 683 /* Turn off stuff in the Transform Engine. */
650 sbus_writel(0, &tec->tec_matrix); 684 sbus_writel(0, &tec->tec_matrix);
651 sbus_writel(0, &tec->tec_clip); 685 sbus_writel(0, &tec->tec_clip);
@@ -814,7 +848,7 @@ static int __devexit cg6_remove(struct of_device *op)
814 return 0; 848 return 0;
815} 849}
816 850
817static struct of_device_id cg6_match[] = { 851static const struct of_device_id cg6_match[] = {
818 { 852 {
819 .name = "cgsix", 853 .name = "cgsix",
820 }, 854 },
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index c14b2435d23e..048b139f0e50 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -327,29 +327,7 @@ static const struct {
327#endif /* CONFIG_ZORRO */ 327#endif /* CONFIG_ZORRO */
328 328
329struct cirrusfb_regs { 329struct cirrusfb_regs {
330 long freq; 330 int multiplexing;
331 long nom;
332 long den;
333 long div;
334 long multiplexing;
335 long mclk;
336 long divMCLK;
337
338 long HorizRes; /* The x resolution in pixel */
339 long HorizTotal;
340 long HorizDispEnd;
341 long HorizBlankStart;
342 long HorizBlankEnd;
343 long HorizSyncStart;
344 long HorizSyncEnd;
345
346 long VertRes; /* the physical y resolution in scanlines */
347 long VertTotal;
348 long VertDispEnd;
349 long VertSyncStart;
350 long VertSyncEnd;
351 long VertBlankStart;
352 long VertBlankEnd;
353}; 331};
354 332
355#ifdef CIRRUSFB_DEBUG 333#ifdef CIRRUSFB_DEBUG
@@ -367,110 +345,13 @@ struct cirrusfb_info {
367 345
368 struct cirrusfb_regs currentmode; 346 struct cirrusfb_regs currentmode;
369 int blank_mode; 347 int blank_mode;
348 u32 pseudo_palette[16];
370 349
371 u32 pseudo_palette[16];
372
373#ifdef CONFIG_ZORRO
374 struct zorro_dev *zdev;
375#endif
376#ifdef CONFIG_PCI
377 struct pci_dev *pdev;
378#endif
379 void (*unmap)(struct fb_info *info); 350 void (*unmap)(struct fb_info *info);
380}; 351};
381 352
382static unsigned cirrusfb_def_mode = 1; 353static int noaccel __devinitdata;
383static int noaccel; 354static char *mode_option __devinitdata = "640x480@60";
384
385/*
386 * Predefined Video Modes
387 */
388
389static const struct {
390 const char *name;
391 struct fb_var_screeninfo var;
392} cirrusfb_predefined[] = {
393 {
394 /* autodetect mode */
395 .name = "Autodetect",
396 }, {
397 /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
398 .name = "640x480",
399 .var = {
400 .xres = 640,
401 .yres = 480,
402 .xres_virtual = 640,
403 .yres_virtual = 480,
404 .bits_per_pixel = 8,
405 .red = { .length = 8 },
406 .green = { .length = 8 },
407 .blue = { .length = 8 },
408 .width = -1,
409 .height = -1,
410 .pixclock = 40000,
411 .left_margin = 48,
412 .right_margin = 16,
413 .upper_margin = 32,
414 .lower_margin = 8,
415 .hsync_len = 96,
416 .vsync_len = 4,
417 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
418 .vmode = FB_VMODE_NONINTERLACED
419 }
420 }, {
421 /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
422 .name = "800x600",
423 .var = {
424 .xres = 800,
425 .yres = 600,
426 .xres_virtual = 800,
427 .yres_virtual = 600,
428 .bits_per_pixel = 8,
429 .red = { .length = 8 },
430 .green = { .length = 8 },
431 .blue = { .length = 8 },
432 .width = -1,
433 .height = -1,
434 .pixclock = 20000,
435 .left_margin = 128,
436 .right_margin = 16,
437 .upper_margin = 24,
438 .lower_margin = 2,
439 .hsync_len = 96,
440 .vsync_len = 6,
441 .vmode = FB_VMODE_NONINTERLACED
442 }
443 }, {
444 /*
445 * Modeline from XF86Config:
446 * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
447 */
448 /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
449 .name = "1024x768",
450 .var = {
451 .xres = 1024,
452 .yres = 768,
453 .xres_virtual = 1024,
454 .yres_virtual = 768,
455 .bits_per_pixel = 8,
456 .red = { .length = 8 },
457 .green = { .length = 8 },
458 .blue = { .length = 8 },
459 .width = -1,
460 .height = -1,
461 .pixclock = 12500,
462 .left_margin = 144,
463 .right_margin = 32,
464 .upper_margin = 30,
465 .lower_margin = 2,
466 .hsync_len = 192,
467 .vsync_len = 6,
468 .vmode = FB_VMODE_NONINTERLACED
469 }
470 }
471};
472
473#define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
474 355
475/****************************************************************************/ 356/****************************************************************************/
476/**** BEGIN PROTOTYPES ******************************************************/ 357/**** BEGIN PROTOTYPES ******************************************************/
@@ -514,10 +395,6 @@ static struct fb_ops cirrusfb_ops = {
514 .fb_imageblit = cirrusfb_imageblit, 395 .fb_imageblit = cirrusfb_imageblit,
515}; 396};
516 397
517/*--- Hardware Specific Routines -------------------------------------------*/
518static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
519 struct cirrusfb_regs *regs,
520 struct fb_info *info);
521/*--- Internal routines ----------------------------------------------------*/ 398/*--- Internal routines ----------------------------------------------------*/
522static void init_vgachip(struct fb_info *info); 399static void init_vgachip(struct fb_info *info);
523static void switch_monitor(struct cirrusfb_info *cinfo, int on); 400static void switch_monitor(struct cirrusfb_info *cinfo, int on);
@@ -546,9 +423,7 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
546 u_short width, u_short height, 423 u_short width, u_short height,
547 u_char color, u_short line_length); 424 u_char color, u_short line_length);
548 425
549static void bestclock(long freq, long *best, 426static void bestclock(long freq, int *nom, int *den, int *div);
550 long *nom, long *den,
551 long *div, long maxfreq);
552 427
553#ifdef CIRRUSFB_DEBUG 428#ifdef CIRRUSFB_DEBUG
554static void cirrusfb_dump(void); 429static void cirrusfb_dump(void);
@@ -584,71 +459,44 @@ static int cirrusfb_release(struct fb_info *info, int user)
584/****************************************************************************/ 459/****************************************************************************/
585/**** BEGIN Hardware specific Routines **************************************/ 460/**** BEGIN Hardware specific Routines **************************************/
586 461
587/* Get a good MCLK value */ 462/* Check if the MCLK is not a better clock source */
588static long cirrusfb_get_mclk(long freq, int bpp, long *div) 463static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq)
589{ 464{
590 long mclk; 465 long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
591
592 assert(div != NULL);
593 466
594 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. 467 /* Read MCLK value */
595 * Assume a 64-bit data path for now. The formula is: 468 mclk = (14318 * mclk) >> 3;
596 * ((B * PCLK * 2)/W) * 1.2 469 DPRINTK("Read MCLK of %ld kHz\n", mclk);
597 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
598 mclk = ((bpp / 8) * freq * 2) / 4;
599 mclk = (mclk * 12) / 10;
600 if (mclk < 50000)
601 mclk = 50000;
602 DPRINTK("Use MCLK of %ld kHz\n", mclk);
603
604 /* Calculate value for SR1F. Multiply by 2 so we can round up. */
605 mclk = ((mclk * 16) / 14318);
606 mclk = (mclk + 1) / 2;
607 DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
608 470
609 /* Determine if we should use MCLK instead of VCLK, and if so, what we 471 /* Determine if we should use MCLK instead of VCLK, and if so, what we
610 * should divide it by to get VCLK */ 472 * should divide it by to get VCLK
611 switch (freq) { 473 */
612 case 24751 ... 25249: 474
613 *div = 2; 475 if (abs(freq - mclk) < 250) {
614 DPRINTK("Using VCLK = MCLK/2\n");
615 break;
616 case 49501 ... 50499:
617 *div = 1;
618 DPRINTK("Using VCLK = MCLK\n"); 476 DPRINTK("Using VCLK = MCLK\n");
619 break; 477 return 1;
620 default: 478 } else if (abs(freq - (mclk / 2)) < 250) {
621 *div = 0; 479 DPRINTK("Using VCLK = MCLK/2\n");
622 break; 480 return 2;
623 } 481 }
624 482
625 return mclk; 483 return 0;
626} 484}
627 485
628static int cirrusfb_check_var(struct fb_var_screeninfo *var, 486static int cirrusfb_check_var(struct fb_var_screeninfo *var,
629 struct fb_info *info) 487 struct fb_info *info)
630{ 488{
631 int nom, den; /* translyting from pixels->bytes */ 489 int yres;
632 int yres, i; 490 /* memory size in pixels */
633 static struct { int xres, yres; } modes[] = 491 unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
634 { { 1600, 1280 },
635 { 1280, 1024 },
636 { 1024, 768 },
637 { 800, 600 },
638 { 640, 480 },
639 { -1, -1 } };
640 492
641 switch (var->bits_per_pixel) { 493 switch (var->bits_per_pixel) {
642 case 1: 494 case 1:
643 nom = 4; 495 pixels /= 4;
644 den = 8;
645 break; /* 8 pixel per byte, only 1/4th of mem usable */ 496 break; /* 8 pixel per byte, only 1/4th of mem usable */
646 case 8: 497 case 8:
647 case 16: 498 case 16:
648 case 24:
649 case 32: 499 case 32:
650 nom = var->bits_per_pixel / 8;
651 den = 1;
652 break; /* 1 pixel == 1 byte */ 500 break; /* 1 pixel == 1 byte */
653 default: 501 default:
654 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." 502 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
@@ -658,43 +506,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
658 return -EINVAL; 506 return -EINVAL;
659 } 507 }
660 508
661 if (var->xres * nom / den * var->yres > info->screen_size) { 509 if (var->xres_virtual < var->xres)
662 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." 510 var->xres_virtual = var->xres;
663 "resolution too high to fit into video memory!\n",
664 var->xres, var->yres, var->bits_per_pixel);
665 DPRINTK("EXIT - EINVAL error\n");
666 return -EINVAL;
667 }
668
669 /* use highest possible virtual resolution */ 511 /* use highest possible virtual resolution */
670 if (var->xres_virtual == -1 && 512 if (var->yres_virtual == -1) {
671 var->yres_virtual == -1) { 513 var->yres_virtual = pixels / var->xres_virtual;
672 printk(KERN_INFO
673 "cirrusfb: using maximum available virtual resolution\n");
674 for (i = 0; modes[i].xres != -1; i++) {
675 int size = modes[i].xres * nom / den * modes[i].yres;
676 if (size < info->screen_size / 2)
677 break;
678 }
679 if (modes[i].xres == -1) {
680 printk(KERN_ERR "cirrusfb: could not find a virtual "
681 "resolution that fits into video memory!!\n");
682 DPRINTK("EXIT - EINVAL error\n");
683 return -EINVAL;
684 }
685 var->xres_virtual = modes[i].xres;
686 var->yres_virtual = modes[i].yres;
687 514
688 printk(KERN_INFO "cirrusfb: virtual resolution set to " 515 printk(KERN_INFO "cirrusfb: virtual resolution set to "
689 "maximum of %dx%d\n", var->xres_virtual, 516 "maximum of %dx%d\n", var->xres_virtual,
690 var->yres_virtual); 517 var->yres_virtual);
691 } 518 }
692
693 if (var->xres_virtual < var->xres)
694 var->xres_virtual = var->xres;
695 if (var->yres_virtual < var->yres) 519 if (var->yres_virtual < var->yres)
696 var->yres_virtual = var->yres; 520 var->yres_virtual = var->yres;
697 521
522 if (var->xres_virtual * var->yres_virtual > pixels) {
523 printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
524 "virtual resolution too high to fit into video memory!\n",
525 var->xres_virtual, var->yres_virtual,
526 var->bits_per_pixel);
527 DPRINTK("EXIT - EINVAL error\n");
528 return -EINVAL;
529 }
530
531
698 if (var->xoffset < 0) 532 if (var->xoffset < 0)
699 var->xoffset = 0; 533 var->xoffset = 0;
700 if (var->yoffset < 0) 534 if (var->yoffset < 0)
@@ -736,7 +570,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
736 var->blue.length = 5; 570 var->blue.length = 5;
737 break; 571 break;
738 572
739 case 24:
740 case 32: 573 case 32:
741 if (isPReP) { 574 if (isPReP) {
742 var->red.offset = 8; 575 var->red.offset = 8;
@@ -790,8 +623,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
790 long maxclock; 623 long maxclock;
791 int maxclockidx = var->bits_per_pixel >> 3; 624 int maxclockidx = var->bits_per_pixel >> 3;
792 struct cirrusfb_info *cinfo = info->par; 625 struct cirrusfb_info *cinfo = info->par;
793 int xres, hfront, hsync, hback;
794 int yres, vfront, vsync, vback;
795 626
796 switch (var->bits_per_pixel) { 627 switch (var->bits_per_pixel) {
797 case 1: 628 case 1:
@@ -805,10 +636,9 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
805 break; 636 break;
806 637
807 case 16: 638 case 16:
808 case 24:
809 case 32: 639 case 32:
810 info->fix.line_length = var->xres_virtual * maxclockidx; 640 info->fix.line_length = var->xres_virtual * maxclockidx;
811 info->fix.visual = FB_VISUAL_DIRECTCOLOR; 641 info->fix.visual = FB_VISUAL_TRUECOLOR;
812 break; 642 break;
813 643
814 default: 644 default:
@@ -850,90 +680,33 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
850 switch (var->bits_per_pixel) { 680 switch (var->bits_per_pixel) {
851 case 16: 681 case 16:
852 case 32: 682 case 32:
853 if (regs->HorizRes <= 800) 683 if (var->xres <= 800)
854 /* Xbh has this type of clock for 32-bit */ 684 /* Xbh has this type of clock for 32-bit */
855 freq /= 2; 685 freq /= 2;
856 break; 686 break;
857 } 687 }
858#endif 688#endif
859
860 bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
861 maxclock);
862 regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
863 &regs->divMCLK);
864
865 xres = var->xres;
866 hfront = var->right_margin;
867 hsync = var->hsync_len;
868 hback = var->left_margin;
869
870 yres = var->yres;
871 vfront = var->lower_margin;
872 vsync = var->vsync_len;
873 vback = var->upper_margin;
874
875 if (var->vmode & FB_VMODE_DOUBLE) {
876 yres *= 2;
877 vfront *= 2;
878 vsync *= 2;
879 vback *= 2;
880 } else if (var->vmode & FB_VMODE_INTERLACED) {
881 yres = (yres + 1) / 2;
882 vfront = (vfront + 1) / 2;
883 vsync = (vsync + 1) / 2;
884 vback = (vback + 1) / 2;
885 }
886 regs->HorizRes = xres;
887 regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
888 regs->HorizDispEnd = xres / 8 - 1;
889 regs->HorizBlankStart = xres / 8;
890 /* does not count with "-5" */
891 regs->HorizBlankEnd = regs->HorizTotal + 5;
892 regs->HorizSyncStart = (xres + hfront) / 8 + 1;
893 regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
894
895 regs->VertRes = yres;
896 regs->VertTotal = yres + vfront + vsync + vback - 2;
897 regs->VertDispEnd = yres - 1;
898 regs->VertBlankStart = yres;
899 regs->VertBlankEnd = regs->VertTotal;
900 regs->VertSyncStart = yres + vfront - 1;
901 regs->VertSyncEnd = yres + vfront + vsync - 1;
902
903 if (regs->VertRes >= 1024) {
904 regs->VertTotal /= 2;
905 regs->VertSyncStart /= 2;
906 regs->VertSyncEnd /= 2;
907 regs->VertDispEnd /= 2;
908 }
909 if (regs->multiplexing) {
910 regs->HorizTotal /= 2;
911 regs->HorizSyncStart /= 2;
912 regs->HorizSyncEnd /= 2;
913 regs->HorizDispEnd /= 2;
914 }
915
916 return 0; 689 return 0;
917} 690}
918 691
919static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val, 692static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo,
920 int div) 693 int div)
921{ 694{
695 unsigned char old1f, old1e;
922 assert(cinfo != NULL); 696 assert(cinfo != NULL);
697 old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
923 698
924 if (div == 2) { 699 if (div) {
925 /* VCLK = MCLK/2 */ 700 DPRINTK("Set %s as pixclock source.\n",
926 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E); 701 (div == 2) ? "MCLK/2" : "MCLK");
927 vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1); 702 old1f |= 0x40;
928 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); 703 old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
929 } else if (div == 1) { 704 if (div == 2)
930 /* VCLK = MCLK */ 705 old1e |= 1;
931 unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E); 706
932 vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1); 707 vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
933 vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
934 } else {
935 vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
936 } 708 }
709 vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
937} 710}
938 711
939/************************************************************************* 712/*************************************************************************
@@ -950,6 +723,10 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
950 unsigned char tmp; 723 unsigned char tmp;
951 int offset = 0, err; 724 int offset = 0, err;
952 const struct cirrusfb_board_info_rec *bi; 725 const struct cirrusfb_board_info_rec *bi;
726 int hdispend, hsyncstart, hsyncend, htotal;
727 int yres, vdispend, vsyncstart, vsyncend, vtotal;
728 long freq;
729 int nom, den, div;
953 730
954 DPRINTK("ENTER\n"); 731 DPRINTK("ENTER\n");
955 DPRINTK("Requested mode: %dx%dx%d\n", 732 DPRINTK("Requested mode: %dx%dx%d\n",
@@ -967,76 +744,117 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
967 744
968 bi = &cirrusfb_board_info[cinfo->btype]; 745 bi = &cirrusfb_board_info[cinfo->btype];
969 746
747 hsyncstart = var->xres + var->right_margin;
748 hsyncend = hsyncstart + var->hsync_len;
749 htotal = (hsyncend + var->left_margin) / 8 - 5;
750 hdispend = var->xres / 8 - 1;
751 hsyncstart = hsyncstart / 8 + 1;
752 hsyncend = hsyncend / 8 + 1;
753
754 yres = var->yres;
755 vsyncstart = yres + var->lower_margin;
756 vsyncend = vsyncstart + var->vsync_len;
757 vtotal = vsyncend + var->upper_margin;
758 vdispend = yres - 1;
759
760 if (var->vmode & FB_VMODE_DOUBLE) {
761 yres *= 2;
762 vsyncstart *= 2;
763 vsyncend *= 2;
764 vtotal *= 2;
765 } else if (var->vmode & FB_VMODE_INTERLACED) {
766 yres = (yres + 1) / 2;
767 vsyncstart = (vsyncstart + 1) / 2;
768 vsyncend = (vsyncend + 1) / 2;
769 vtotal = (vtotal + 1) / 2;
770 }
771
772 vtotal -= 2;
773 vsyncstart -= 1;
774 vsyncend -= 1;
775
776 if (yres >= 1024) {
777 vtotal /= 2;
778 vsyncstart /= 2;
779 vsyncend /= 2;
780 vdispend /= 2;
781 }
782 if (regs.multiplexing) {
783 htotal /= 2;
784 hsyncstart /= 2;
785 hsyncend /= 2;
786 hdispend /= 2;
787 }
970 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ 788 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
971 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ 789 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
972 790
973 /* if debugging is enabled, all parameters get output before writing */ 791 /* if debugging is enabled, all parameters get output before writing */
974 DPRINTK("CRT0: %ld\n", regs.HorizTotal); 792 DPRINTK("CRT0: %d\n", htotal);
975 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal); 793 vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
976 794
977 DPRINTK("CRT1: %ld\n", regs.HorizDispEnd); 795 DPRINTK("CRT1: %d\n", hdispend);
978 vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd); 796 vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
979 797
980 DPRINTK("CRT2: %ld\n", regs.HorizBlankStart); 798 DPRINTK("CRT2: %d\n", var->xres / 8);
981 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart); 799 vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
982 800
983 /* + 128: Compatible read */ 801 /* + 128: Compatible read */
984 DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); 802 DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32);
985 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, 803 vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
986 128 + (regs.HorizBlankEnd % 32)); 804 128 + ((htotal + 5) % 32));
987 805
988 DPRINTK("CRT4: %ld\n", regs.HorizSyncStart); 806 DPRINTK("CRT4: %d\n", hsyncstart);
989 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart); 807 vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
990 808
991 tmp = regs.HorizSyncEnd % 32; 809 tmp = hsyncend % 32;
992 if (regs.HorizBlankEnd & 32) 810 if ((htotal + 5) & 32)
993 tmp += 128; 811 tmp += 128;
994 DPRINTK("CRT5: %d\n", tmp); 812 DPRINTK("CRT5: %d\n", tmp);
995 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); 813 vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
996 814
997 DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff); 815 DPRINTK("CRT6: %d\n", vtotal & 0xff);
998 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff)); 816 vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
999 817
1000 tmp = 16; /* LineCompare bit #9 */ 818 tmp = 16; /* LineCompare bit #9 */
1001 if (regs.VertTotal & 256) 819 if (vtotal & 256)
1002 tmp |= 1; 820 tmp |= 1;
1003 if (regs.VertDispEnd & 256) 821 if (vdispend & 256)
1004 tmp |= 2; 822 tmp |= 2;
1005 if (regs.VertSyncStart & 256) 823 if (vsyncstart & 256)
1006 tmp |= 4; 824 tmp |= 4;
1007 if (regs.VertBlankStart & 256) 825 if ((vdispend + 1) & 256)
1008 tmp |= 8; 826 tmp |= 8;
1009 if (regs.VertTotal & 512) 827 if (vtotal & 512)
1010 tmp |= 32; 828 tmp |= 32;
1011 if (regs.VertDispEnd & 512) 829 if (vdispend & 512)
1012 tmp |= 64; 830 tmp |= 64;
1013 if (regs.VertSyncStart & 512) 831 if (vsyncstart & 512)
1014 tmp |= 128; 832 tmp |= 128;
1015 DPRINTK("CRT7: %d\n", tmp); 833 DPRINTK("CRT7: %d\n", tmp);
1016 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); 834 vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
1017 835
1018 tmp = 0x40; /* LineCompare bit #8 */ 836 tmp = 0x40; /* LineCompare bit #8 */
1019 if (regs.VertBlankStart & 512) 837 if ((vdispend + 1) & 512)
1020 tmp |= 0x20; 838 tmp |= 0x20;
1021 if (var->vmode & FB_VMODE_DOUBLE) 839 if (var->vmode & FB_VMODE_DOUBLE)
1022 tmp |= 0x80; 840 tmp |= 0x80;
1023 DPRINTK("CRT9: %d\n", tmp); 841 DPRINTK("CRT9: %d\n", tmp);
1024 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); 842 vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
1025 843
1026 DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff); 844 DPRINTK("CRT10: %d\n", vsyncstart & 0xff);
1027 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff); 845 vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
1028 846
1029 DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16); 847 DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16);
1030 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32); 848 vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
1031 849
1032 DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff); 850 DPRINTK("CRT12: %d\n", vdispend & 0xff);
1033 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff); 851 vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
1034 852
1035 DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff); 853 DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff);
1036 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff); 854 vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
1037 855
1038 DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff); 856 DPRINTK("CRT16: %d\n", vtotal & 0xff);
1039 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff); 857 vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
1040 858
1041 DPRINTK("CRT18: 0xff\n"); 859 DPRINTK("CRT18: 0xff\n");
1042 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); 860 vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
@@ -1044,38 +862,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1044 tmp = 0; 862 tmp = 0;
1045 if (var->vmode & FB_VMODE_INTERLACED) 863 if (var->vmode & FB_VMODE_INTERLACED)
1046 tmp |= 1; 864 tmp |= 1;
1047 if (regs.HorizBlankEnd & 64) 865 if ((htotal + 5) & 64)
1048 tmp |= 16; 866 tmp |= 16;
1049 if (regs.HorizBlankEnd & 128) 867 if ((htotal + 5) & 128)
1050 tmp |= 32; 868 tmp |= 32;
1051 if (regs.VertBlankEnd & 256) 869 if (vtotal & 256)
1052 tmp |= 64; 870 tmp |= 64;
1053 if (regs.VertBlankEnd & 512) 871 if (vtotal & 512)
1054 tmp |= 128; 872 tmp |= 128;
1055 873
1056 DPRINTK("CRT1a: %d\n", tmp); 874 DPRINTK("CRT1a: %d\n", tmp);
1057 vga_wcrt(regbase, CL_CRT1A, tmp); 875 vga_wcrt(regbase, CL_CRT1A, tmp);
1058 876
877 freq = PICOS2KHZ(var->pixclock);
878 bestclock(freq, &nom, &den, &div);
879
1059 /* set VCLK0 */ 880 /* set VCLK0 */
1060 /* hardware RefClock: 14.31818 MHz */ 881 /* hardware RefClock: 14.31818 MHz */
1061 /* formula: VClk = (OSC * N) / (D * (1+P)) */ 882 /* formula: VClk = (OSC * N) / (D * (1+P)) */
1062 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ 883 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1063 884
1064 vga_wseq(regbase, CL_SEQRB, regs.nom); 885 if (cinfo->btype == BT_ALPINE) {
1065 tmp = regs.den << 1; 886 /* if freq is close to mclk or mclk/2 select mclk
1066 if (regs.div != 0) 887 * as clock source
1067 tmp |= 1; 888 */
889 int divMCLK = cirrusfb_check_mclk(cinfo, freq);
890 if (divMCLK) {
891 nom = 0;
892 cirrusfb_set_mclk_as_source(cinfo, divMCLK);
893 }
894 }
895 if (nom) {
896 vga_wseq(regbase, CL_SEQRB, nom);
897 tmp = den << 1;
898 if (div != 0)
899 tmp |= 1;
1068 900
1069 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ 901 /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1070 if ((cinfo->btype == BT_SD64) || 902 if ((cinfo->btype == BT_SD64) ||
1071 (cinfo->btype == BT_ALPINE) || 903 (cinfo->btype == BT_ALPINE) ||
1072 (cinfo->btype == BT_GD5480)) 904 (cinfo->btype == BT_GD5480))
1073 tmp |= 0x80; 905 tmp |= 0x80;
1074 906
1075 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); 907 DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
1076 vga_wseq(regbase, CL_SEQR1B, tmp); 908 vga_wseq(regbase, CL_SEQR1B, tmp);
909 }
1077 910
1078 if (regs.VertRes >= 1024) 911 if (yres >= 1024)
1079 /* 1280x1024 */ 912 /* 1280x1024 */
1080 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); 913 vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
1081 else 914 else
@@ -1089,7 +922,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1089 /* don't know if it would hurt to also program this if no interlaced */ 922 /* don't know if it would hurt to also program this if no interlaced */
1090 /* mode is used, but I feel better this way.. :-) */ 923 /* mode is used, but I feel better this way.. :-) */
1091 if (var->vmode & FB_VMODE_INTERLACED) 924 if (var->vmode & FB_VMODE_INTERLACED)
1092 vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2); 925 vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
1093 else 926 else
1094 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ 927 vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
1095 928
@@ -1263,7 +1096,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1263 1096
1264 case BT_ALPINE: 1097 case BT_ALPINE:
1265 DPRINTK(" (for GD543x)\n"); 1098 DPRINTK(" (for GD543x)\n");
1266 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1267 /* We already set SRF and SR1F */ 1099 /* We already set SRF and SR1F */
1268 break; 1100 break;
1269 1101
@@ -1335,11 +1167,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1335 1167
1336 case BT_ALPINE: 1168 case BT_ALPINE:
1337 DPRINTK(" (for GD543x)\n"); 1169 DPRINTK(" (for GD543x)\n");
1338 if (regs.HorizRes >= 1024) 1170 vga_wseq(regbase, CL_SEQR7, 0xa7);
1339 vga_wseq(regbase, CL_SEQR7, 0xa7);
1340 else
1341 vga_wseq(regbase, CL_SEQR7, 0xa3);
1342 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1343 break; 1171 break;
1344 1172
1345 case BT_GD5480: 1173 case BT_GD5480:
@@ -1383,7 +1211,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1383 */ 1211 */
1384 1212
1385 else if (var->bits_per_pixel == 32) { 1213 else if (var->bits_per_pixel == 32) {
1386 DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n"); 1214 DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
1387 switch (cinfo->btype) { 1215 switch (cinfo->btype) {
1388 case BT_SD64: 1216 case BT_SD64:
1389 /* Extended Sequencer Mode: 256c col. mode */ 1217 /* Extended Sequencer Mode: 256c col. mode */
@@ -1417,7 +1245,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
1417 case BT_ALPINE: 1245 case BT_ALPINE:
1418 DPRINTK(" (for GD543x)\n"); 1246 DPRINTK(" (for GD543x)\n");
1419 vga_wseq(regbase, CL_SEQR7, 0xa9); 1247 vga_wseq(regbase, CL_SEQR7, 0xa9);
1420 cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
1421 break; 1248 break;
1422 1249
1423 case BT_GD5480: 1250 case BT_GD5480:
@@ -1972,8 +1799,6 @@ static void init_vgachip(struct fb_info *info)
1972 /* misc... */ 1799 /* misc... */
1973 WHDR(cinfo, 0); /* Hidden DAC register: - */ 1800 WHDR(cinfo, 0); /* Hidden DAC register: - */
1974 1801
1975 printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
1976 info->screen_size);
1977 DPRINTK("EXIT\n"); 1802 DPRINTK("EXIT\n");
1978 return; 1803 return;
1979} 1804}
@@ -2145,7 +1970,7 @@ static int release_io_ports;
2145 * based on the DRAM bandwidth bit and DRAM bank switching bit. This 1970 * based on the DRAM bandwidth bit and DRAM bank switching bit. This
2146 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards 1971 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2147 * seem to have. */ 1972 * seem to have. */
2148static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase) 1973static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
2149{ 1974{
2150 unsigned long mem; 1975 unsigned long mem;
2151 unsigned char SRF; 1976 unsigned char SRF;
@@ -2211,8 +2036,7 @@ static void get_pci_addrs(const struct pci_dev *pdev,
2211 2036
2212static void cirrusfb_pci_unmap(struct fb_info *info) 2037static void cirrusfb_pci_unmap(struct fb_info *info)
2213{ 2038{
2214 struct cirrusfb_info *cinfo = info->par; 2039 struct pci_dev *pdev = to_pci_dev(info->device);
2215 struct pci_dev *pdev = cinfo->pdev;
2216 2040
2217 iounmap(info->screen_base); 2041 iounmap(info->screen_base);
2218#if 0 /* if system didn't claim this region, we would... */ 2042#if 0 /* if system didn't claim this region, we would... */
@@ -2228,20 +2052,22 @@ static void cirrusfb_pci_unmap(struct fb_info *info)
2228static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) 2052static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
2229{ 2053{
2230 struct cirrusfb_info *cinfo = info->par; 2054 struct cirrusfb_info *cinfo = info->par;
2231 zorro_release_device(cinfo->zdev); 2055 struct zorro_dev *zdev = to_zorro_dev(info->device);
2056
2057 zorro_release_device(zdev);
2232 2058
2233 if (cinfo->btype == BT_PICASSO4) { 2059 if (cinfo->btype == BT_PICASSO4) {
2234 cinfo->regbase -= 0x600000; 2060 cinfo->regbase -= 0x600000;
2235 iounmap((void *)cinfo->regbase); 2061 iounmap((void *)cinfo->regbase);
2236 iounmap(info->screen_base); 2062 iounmap(info->screen_base);
2237 } else { 2063 } else {
2238 if (zorro_resource_start(cinfo->zdev) > 0x01000000) 2064 if (zorro_resource_start(zdev) > 0x01000000)
2239 iounmap(info->screen_base); 2065 iounmap(info->screen_base);
2240 } 2066 }
2241} 2067}
2242#endif /* CONFIG_ZORRO */ 2068#endif /* CONFIG_ZORRO */
2243 2069
2244static int cirrusfb_set_fbinfo(struct fb_info *info) 2070static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
2245{ 2071{
2246 struct cirrusfb_info *cinfo = info->par; 2072 struct cirrusfb_info *cinfo = info->par;
2247 struct fb_var_screeninfo *var = &info->var; 2073 struct fb_var_screeninfo *var = &info->var;
@@ -2258,7 +2084,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
2258 if (cinfo->btype == BT_GD5480) { 2084 if (cinfo->btype == BT_GD5480) {
2259 if (var->bits_per_pixel == 16) 2085 if (var->bits_per_pixel == 16)
2260 info->screen_base += 1 * MB_; 2086 info->screen_base += 1 * MB_;
2261 if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32) 2087 if (var->bits_per_pixel == 32)
2262 info->screen_base += 2 * MB_; 2088 info->screen_base += 2 * MB_;
2263 } 2089 }
2264 2090
@@ -2285,7 +2111,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
2285 return 0; 2111 return 0;
2286} 2112}
2287 2113
2288static int cirrusfb_register(struct fb_info *info) 2114static int __devinit cirrusfb_register(struct fb_info *info)
2289{ 2115{
2290 struct cirrusfb_info *cinfo = info->par; 2116 struct cirrusfb_info *cinfo = info->par;
2291 int err; 2117 int err;
@@ -2301,23 +2127,27 @@ static int cirrusfb_register(struct fb_info *info)
2301 /* sanity checks */ 2127 /* sanity checks */
2302 assert(btype != BT_NONE); 2128 assert(btype != BT_NONE);
2303 2129
2130 /* set all the vital stuff */
2131 cirrusfb_set_fbinfo(info);
2132
2304 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); 2133 DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
2305 2134
2306 /* Make pretend we've set the var so our structures are in a "good" */ 2135 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
2307 /* state, even though we haven't written the mode to the hw yet... */ 2136 if (!err) {
2308 info->var = cirrusfb_predefined[cirrusfb_def_mode].var; 2137 DPRINTK("wrong initial video mode\n");
2138 err = -EINVAL;
2139 goto err_dealloc_cmap;
2140 }
2141
2309 info->var.activate = FB_ACTIVATE_NOW; 2142 info->var.activate = FB_ACTIVATE_NOW;
2310 2143
2311 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); 2144 err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
2312 if (err < 0) { 2145 if (err < 0) {
2313 /* should never happen */ 2146 /* should never happen */
2314 DPRINTK("choking on default var... umm, no good.\n"); 2147 DPRINTK("choking on default var... umm, no good.\n");
2315 goto err_unmap_cirrusfb; 2148 goto err_dealloc_cmap;
2316 } 2149 }
2317 2150
2318 /* set all the vital stuff */
2319 cirrusfb_set_fbinfo(info);
2320
2321 err = register_framebuffer(info); 2151 err = register_framebuffer(info);
2322 if (err < 0) { 2152 if (err < 0) {
2323 printk(KERN_ERR "cirrusfb: could not register " 2153 printk(KERN_ERR "cirrusfb: could not register "
@@ -2330,7 +2160,6 @@ static int cirrusfb_register(struct fb_info *info)
2330 2160
2331err_dealloc_cmap: 2161err_dealloc_cmap:
2332 fb_dealloc_cmap(&info->cmap); 2162 fb_dealloc_cmap(&info->cmap);
2333err_unmap_cirrusfb:
2334 cinfo->unmap(info); 2163 cinfo->unmap(info);
2335 framebuffer_release(info); 2164 framebuffer_release(info);
2336 return err; 2165 return err;
@@ -2353,8 +2182,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info)
2353} 2182}
2354 2183
2355#ifdef CONFIG_PCI 2184#ifdef CONFIG_PCI
2356static int cirrusfb_pci_register(struct pci_dev *pdev, 2185static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
2357 const struct pci_device_id *ent) 2186 const struct pci_device_id *ent)
2358{ 2187{
2359 struct cirrusfb_info *cinfo; 2188 struct cirrusfb_info *cinfo;
2360 struct fb_info *info; 2189 struct fb_info *info;
@@ -2376,7 +2205,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
2376 } 2205 }
2377 2206
2378 cinfo = info->par; 2207 cinfo = info->par;
2379 cinfo->pdev = pdev;
2380 cinfo->btype = btype = (enum cirrus_board) ent->driver_data; 2208 cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
2381 2209
2382 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", 2210 DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
@@ -2482,8 +2310,8 @@ static struct pci_driver cirrusfb_pci_driver = {
2482#endif /* CONFIG_PCI */ 2310#endif /* CONFIG_PCI */
2483 2311
2484#ifdef CONFIG_ZORRO 2312#ifdef CONFIG_ZORRO
2485static int cirrusfb_zorro_register(struct zorro_dev *z, 2313static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2486 const struct zorro_device_id *ent) 2314 const struct zorro_device_id *ent)
2487{ 2315{
2488 struct cirrusfb_info *cinfo; 2316 struct cirrusfb_info *cinfo;
2489 struct fb_info *info; 2317 struct fb_info *info;
@@ -2512,7 +2340,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
2512 assert(z); 2340 assert(z);
2513 assert(btype != BT_NONE); 2341 assert(btype != BT_NONE);
2514 2342
2515 cinfo->zdev = z;
2516 board_addr = zorro_resource_start(z); 2343 board_addr = zorro_resource_start(z);
2517 board_size = zorro_resource_len(z); 2344 board_size = zorro_resource_len(z);
2518 info->screen_size = size; 2345 info->screen_size = size;
@@ -2644,17 +2471,17 @@ static int __init cirrusfb_setup(char *options) {
2644 return 0; 2471 return 0;
2645 2472
2646 while ((this_opt = strsep(&options, ",")) != NULL) { 2473 while ((this_opt = strsep(&options, ",")) != NULL) {
2647 if (!*this_opt) continue; 2474 if (!*this_opt)
2475 continue;
2648 2476
2649 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); 2477 DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
2650 2478
2651 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2652 sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
2653 if (strcmp(this_opt, s) == 0)
2654 cirrusfb_def_mode = i;
2655 }
2656 if (!strcmp(this_opt, "noaccel")) 2479 if (!strcmp(this_opt, "noaccel"))
2657 noaccel = 1; 2480 noaccel = 1;
2481 else if (!strncmp(this_opt, "mode:", 5))
2482 mode_option = this_opt + 5;
2483 else
2484 mode_option = this_opt;
2658 } 2485 }
2659 return 0; 2486 return 0;
2660} 2487}
@@ -2680,6 +2507,11 @@ static void __exit cirrusfb_exit(void)
2680 2507
2681module_init(cirrusfb_init); 2508module_init(cirrusfb_init);
2682 2509
2510module_param(mode_option, charp, 0);
2511MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
2512module_param(noaccel, bool, 0);
2513MODULE_PARM_DESC(noaccel, "Disable acceleration");
2514
2683#ifdef MODULE 2515#ifdef MODULE
2684module_exit(cirrusfb_exit); 2516module_exit(cirrusfb_exit);
2685#endif 2517#endif
@@ -3073,16 +2905,14 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
3073 * bestclock() - determine closest possible clock lower(?) than the 2905 * bestclock() - determine closest possible clock lower(?) than the
3074 * desired pixel clock 2906 * desired pixel clock
3075 **************************************************************************/ 2907 **************************************************************************/
3076static void bestclock(long freq, long *best, long *nom, 2908static void bestclock(long freq, int *nom, int *den, int *div)
3077 long *den, long *div, long maxfreq)
3078{ 2909{
3079 long n, h, d, f; 2910 int n, d;
2911 long h, diff;
3080 2912
3081 assert(best != NULL);
3082 assert(nom != NULL); 2913 assert(nom != NULL);
3083 assert(den != NULL); 2914 assert(den != NULL);
3084 assert(div != NULL); 2915 assert(div != NULL);
3085 assert(maxfreq > 0);
3086 2916
3087 *nom = 0; 2917 *nom = 0;
3088 *den = 0; 2918 *den = 0;
@@ -3093,51 +2923,47 @@ static void bestclock(long freq, long *best, long *nom,
3093 if (freq < 8000) 2923 if (freq < 8000)
3094 freq = 8000; 2924 freq = 8000;
3095 2925
3096 if (freq > maxfreq) 2926 diff = freq;
3097 freq = maxfreq;
3098
3099 *best = 0;
3100 f = freq * 10;
3101 2927
3102 for (n = 32; n < 128; n++) { 2928 for (n = 32; n < 128; n++) {
3103 d = (143181 * n) / f; 2929 int s = 0;
2930
2931 d = (14318 * n) / freq;
3104 if ((d >= 7) && (d <= 63)) { 2932 if ((d >= 7) && (d <= 63)) {
3105 if (d > 31) 2933 int temp = d;
3106 d = (d / 2) * 2; 2934
3107 h = (14318 * n) / d; 2935 if (temp > 31) {
3108 if (abs(h - freq) < abs(*best - freq)) { 2936 s = 1;
3109 *best = h; 2937 temp >>= 1;
2938 }
2939 h = ((14318 * n) / temp) >> s;
2940 h = h > freq ? h - freq : freq - h;
2941 if (h < diff) {
2942 diff = h;
3110 *nom = n; 2943 *nom = n;
3111 if (d < 32) { 2944 *den = temp;
3112 *den = d; 2945 *div = s;
3113 *div = 0;
3114 } else {
3115 *den = d / 2;
3116 *div = 1;
3117 }
3118 } 2946 }
3119 } 2947 }
3120 d = DIV_ROUND_UP(143181 * n, f); 2948 d++;
3121 if ((d >= 7) && (d <= 63)) { 2949 if ((d >= 7) && (d <= 63)) {
3122 if (d > 31) 2950 if (d > 31) {
3123 d = (d / 2) * 2; 2951 s = 1;
3124 h = (14318 * n) / d; 2952 d >>= 1;
3125 if (abs(h - freq) < abs(*best - freq)) { 2953 }
3126 *best = h; 2954 h = ((14318 * n) / d) >> s;
2955 h = h > freq ? h - freq : freq - h;
2956 if (h < diff) {
2957 diff = h;
3127 *nom = n; 2958 *nom = n;
3128 if (d < 32) { 2959 *den = d;
3129 *den = d; 2960 *div = s;
3130 *div = 0;
3131 } else {
3132 *den = d / 2;
3133 *div = 1;
3134 }
3135 } 2961 }
3136 } 2962 }
3137 } 2963 }
3138 2964
3139 DPRINTK("Best possible values for given frequency:\n"); 2965 DPRINTK("Best possible values for given frequency:\n");
3140 DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n", 2966 DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n",
3141 freq, *nom, *den, *div); 2967 freq, *nom, *den, *div);
3142 2968
3143 DPRINTK("EXIT\n"); 2969 DPRINTK("EXIT\n");
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index 9f8a389dc7ae..16f5db471ab5 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -27,12 +27,12 @@
27#include <linux/proc_fs.h> 27#include <linux/proc_fs.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29 29
30#include <asm/hardware.h> 30#include <mach/hardware.h>
31#include <asm/mach-types.h> 31#include <asm/mach-types.h>
32#include <linux/uaccess.h> 32#include <linux/uaccess.h>
33 33
34#include <asm/hardware/clps7111.h> 34#include <asm/hardware/clps7111.h>
35#include <asm/arch/syspld.h> 35#include <mach/syspld.h>
36 36
37struct fb_info *cfb; 37struct fb_info *cfb;
38 38
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
new file mode 100644
index 000000000000..7bad24ed04ef
--- /dev/null
+++ b/drivers/video/cobalt_lcdfb.c
@@ -0,0 +1,371 @@
1/*
2 * Cobalt server LCD frame buffer driver.
3 *
4 * Copyright (C) 2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20#include <linux/delay.h>
21#include <linux/fb.h>
22#include <linux/init.h>
23#include <linux/io.h>
24#include <linux/ioport.h>
25#include <linux/uaccess.h>
26#include <linux/platform_device.h>
27
28/*
29 * Cursor position address
30 * \X 0 1 2 ... 14 15
31 * Y+----+----+----+---+----+----+
32 * 0|0x00|0x01|0x02|...|0x0e|0x0f|
33 * +----+----+----+---+----+----+
34 * 1|0x40|0x41|0x42|...|0x4e|0x4f|
35 * +----+----+----+---+----+----+
36 */
37#define LCD_DATA_REG_OFFSET 0x10
38#define LCD_XRES_MAX 16
39#define LCD_YRES_MAX 2
40#define LCD_CHARS_MAX 32
41
42#define LCD_CLEAR 0x01
43#define LCD_CURSOR_MOVE_HOME 0x02
44#define LCD_RESET 0x06
45#define LCD_OFF 0x08
46#define LCD_CURSOR_OFF 0x0c
47#define LCD_CURSOR_BLINK_OFF 0x0e
48#define LCD_CURSOR_ON 0x0f
49#define LCD_ON LCD_CURSOR_ON
50#define LCD_CURSOR_MOVE_LEFT 0x10
51#define LCD_CURSOR_MOVE_RIGHT 0x14
52#define LCD_DISPLAY_LEFT 0x18
53#define LCD_DISPLAY_RIGHT 0x1c
54#define LCD_PRERESET 0x3f /* execute 4 times continuously */
55#define LCD_BUSY 0x80
56
57#define LCD_GRAPHIC_MODE 0x40
58#define LCD_TEXT_MODE 0x80
59#define LCD_CUR_POS_MASK 0x7f
60
61#define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK)
62#define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE)
63
64static inline void lcd_write_control(struct fb_info *info, u8 control)
65{
66 writel((u32)control << 24, info->screen_base);
67}
68
69static inline u8 lcd_read_control(struct fb_info *info)
70{
71 return readl(info->screen_base) >> 24;
72}
73
74static inline void lcd_write_data(struct fb_info *info, u8 data)
75{
76 writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET);
77}
78
79static inline u8 lcd_read_data(struct fb_info *info)
80{
81 return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
82}
83
84static int lcd_busy_wait(struct fb_info *info)
85{
86 u8 val = 0;
87 int timeout = 10, retval = 0;
88
89 do {
90 val = lcd_read_control(info);
91 val &= LCD_BUSY;
92 if (val != LCD_BUSY)
93 break;
94
95 if (msleep_interruptible(1))
96 return -EINTR;
97
98 timeout--;
99 } while (timeout);
100
101 if (val == LCD_BUSY)
102 retval = -EBUSY;
103
104 return retval;
105}
106
107static void lcd_clear(struct fb_info *info)
108{
109 int i;
110
111 for (i = 0; i < 4; i++) {
112 udelay(150);
113
114 lcd_write_control(info, LCD_PRERESET);
115 }
116
117 udelay(150);
118
119 lcd_write_control(info, LCD_CLEAR);
120
121 udelay(150);
122
123 lcd_write_control(info, LCD_RESET);
124}
125
126static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = {
127 .id = "cobalt-lcd",
128 .type = FB_TYPE_TEXT,
129 .type_aux = FB_AUX_TEXT_MDA,
130 .visual = FB_VISUAL_MONO01,
131 .line_length = LCD_XRES_MAX,
132 .accel = FB_ACCEL_NONE,
133};
134
135static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf,
136 size_t count, loff_t *ppos)
137{
138 char src[LCD_CHARS_MAX];
139 unsigned long pos;
140 int len, retval = 0;
141
142 pos = *ppos;
143 if (pos >= LCD_CHARS_MAX || count == 0)
144 return 0;
145
146 if (count > LCD_CHARS_MAX)
147 count = LCD_CHARS_MAX;
148
149 if (pos + count > LCD_CHARS_MAX)
150 count = LCD_CHARS_MAX - pos;
151
152 for (len = 0; len < count; len++) {
153 retval = lcd_busy_wait(info);
154 if (retval < 0)
155 break;
156
157 lcd_write_control(info, LCD_TEXT_POS(pos));
158
159 retval = lcd_busy_wait(info);
160 if (retval < 0)
161 break;
162
163 src[len] = lcd_read_data(info);
164 if (pos == 0x0f)
165 pos = 0x40;
166 else
167 pos++;
168 }
169
170 if (retval < 0 && signal_pending(current))
171 return -ERESTARTSYS;
172
173 if (copy_to_user(buf, src, len))
174 return -EFAULT;
175
176 *ppos += len;
177
178 return len;
179}
180
181static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf,
182 size_t count, loff_t *ppos)
183{
184 char dst[LCD_CHARS_MAX];
185 unsigned long pos;
186 int len, retval = 0;
187
188 pos = *ppos;
189 if (pos >= LCD_CHARS_MAX || count == 0)
190 return 0;
191
192 if (count > LCD_CHARS_MAX)
193 count = LCD_CHARS_MAX;
194
195 if (pos + count > LCD_CHARS_MAX)
196 count = LCD_CHARS_MAX - pos;
197
198 if (copy_from_user(dst, buf, count))
199 return -EFAULT;
200
201 for (len = 0; len < count; len++) {
202 retval = lcd_busy_wait(info);
203 if (retval < 0)
204 break;
205
206 lcd_write_control(info, LCD_TEXT_POS(pos));
207
208 retval = lcd_busy_wait(info);
209 if (retval < 0)
210 break;
211
212 lcd_write_data(info, dst[len]);
213 if (pos == 0x0f)
214 pos = 0x40;
215 else
216 pos++;
217 }
218
219 if (retval < 0 && signal_pending(current))
220 return -ERESTARTSYS;
221
222 *ppos += len;
223
224 return len;
225}
226
227static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info)
228{
229 int retval;
230
231 retval = lcd_busy_wait(info);
232 if (retval < 0)
233 return retval;
234
235 switch (blank_mode) {
236 case FB_BLANK_UNBLANK:
237 lcd_write_control(info, LCD_ON);
238 break;
239 default:
240 lcd_write_control(info, LCD_OFF);
241 break;
242 }
243
244 return 0;
245}
246
247static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
248{
249 u32 x, y;
250 int retval;
251
252 switch (cursor->set) {
253 case FB_CUR_SETPOS:
254 x = cursor->image.dx;
255 y = cursor->image.dy;
256 if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX)
257 return -EINVAL;
258
259 retval = lcd_busy_wait(info);
260 if (retval < 0)
261 return retval;
262
263 lcd_write_control(info,
264 LCD_TEXT_POS(info->fix.line_length * y + x));
265 break;
266 default:
267 return -EINVAL;
268 }
269
270 retval = lcd_busy_wait(info);
271 if (retval < 0)
272 return retval;
273
274 if (cursor->enable)
275 lcd_write_control(info, LCD_CURSOR_ON);
276 else
277 lcd_write_control(info, LCD_CURSOR_OFF);
278
279 return 0;
280}
281
282static struct fb_ops cobalt_lcd_fbops = {
283 .owner = THIS_MODULE,
284 .fb_read = cobalt_lcdfb_read,
285 .fb_write = cobalt_lcdfb_write,
286 .fb_blank = cobalt_lcdfb_blank,
287 .fb_cursor = cobalt_lcdfb_cursor,
288};
289
290static int __init cobalt_lcdfb_probe(struct platform_device *dev)
291{
292 struct fb_info *info;
293 struct resource *res;
294 int retval;
295
296 info = framebuffer_alloc(0, &dev->dev);
297 if (!info)
298 return -ENOMEM;
299
300 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
301 if (!res) {
302 framebuffer_release(info);
303 return -EBUSY;
304 }
305
306 info->screen_size = res->end - res->start + 1;
307 info->screen_base = ioremap(res->start, info->screen_size);
308 info->fbops = &cobalt_lcd_fbops;
309 info->fix = cobalt_lcdfb_fix;
310 info->fix.smem_start = res->start;
311 info->fix.smem_len = info->screen_size;
312 info->pseudo_palette = NULL;
313 info->par = NULL;
314 info->flags = FBINFO_DEFAULT;
315
316 retval = register_framebuffer(info);
317 if (retval < 0) {
318 iounmap(info->screen_base);
319 framebuffer_release(info);
320 return retval;
321 }
322
323 platform_set_drvdata(dev, info);
324
325 lcd_clear(info);
326
327 printk(KERN_INFO "fb%d: Cobalt server LCD frame buffer device\n",
328 info->node);
329
330 return 0;
331}
332
333static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
334{
335 struct fb_info *info;
336
337 info = platform_get_drvdata(dev);
338 if (info) {
339 iounmap(info->screen_base);
340 unregister_framebuffer(info);
341 framebuffer_release(info);
342 }
343
344 return 0;
345}
346
347static struct platform_driver cobalt_lcdfb_driver = {
348 .probe = cobalt_lcdfb_probe,
349 .remove = __devexit_p(cobalt_lcdfb_remove),
350 .driver = {
351 .name = "cobalt-lcd",
352 .owner = THIS_MODULE,
353 },
354};
355
356static int __init cobalt_lcdfb_init(void)
357{
358 return platform_driver_register(&cobalt_lcdfb_driver);
359}
360
361static void __exit cobalt_lcdfb_exit(void)
362{
363 platform_driver_unregister(&cobalt_lcdfb_driver);
364}
365
366module_init(cobalt_lcdfb_init);
367module_exit(cobalt_lcdfb_exit);
368
369MODULE_LICENSE("GPL v2");
370MODULE_AUTHOR("Yoichi Yuasa");
371MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver");
diff --git a/drivers/video/console/.gitignore b/drivers/video/console/.gitignore
new file mode 100644
index 000000000000..0c258b45439c
--- /dev/null
+++ b/drivers/video/console/.gitignore
@@ -0,0 +1,2 @@
1# conmakehash generated file
2promcon_tbl.c
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 06f87b04f207..2f50a80b413e 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,22 +43,6 @@ config VGACON_SOFT_SCROLLBACK_SIZE
43 buffer. Each 64KB will give you approximately 16 80x25 43 buffer. Each 64KB will give you approximately 16 80x25
44 screenfuls of scrollback buffer 44 screenfuls of scrollback buffer
45 45
46config VIDEO_SELECT
47 bool "Video mode selection support"
48 depends on X86 && VGA_CONSOLE
49 ---help---
50 This enables support for text mode selection on kernel startup. If
51 you want to take advantage of some high-resolution text mode your
52 card's BIOS offers, but the traditional Linux utilities like
53 SVGATextMode don't, you can say Y here and set the mode using the
54 "vga=" option from your boot loader (lilo or loadlin) or set
55 "vga=ask" which brings up a video mode menu on kernel startup. (Try
56 "man bootparam" or see the documentation of your boot loader about
57 how to pass options to the kernel.)
58
59 Read the file <file:Documentation/svga.txt> for more information
60 about the Video mode selection support. If unsure, say N.
61
62config MDA_CONSOLE 46config MDA_CONSOLE
63 depends on !M68K && !PARISC && ISA 47 depends on !M68K && !PARISC && ISA
64 tristate "MDA text console (dual-headed) (EXPERIMENTAL)" 48 tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 97aff8db10bf..64b3d30027b8 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,9 +107,7 @@ static struct display fb_display[MAX_NR_CONSOLES];
107 107
108static signed char con2fb_map[MAX_NR_CONSOLES]; 108static signed char con2fb_map[MAX_NR_CONSOLES];
109static signed char con2fb_map_boot[MAX_NR_CONSOLES]; 109static signed char con2fb_map_boot[MAX_NR_CONSOLES];
110#ifndef MODULE 110
111static int logo_height;
112#endif
113static int logo_lines; 111static int logo_lines;
114/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO 112/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
115 enums. */ 113 enums. */
@@ -607,6 +605,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
607 struct fbcon_ops *ops = info->fbcon_par; 605 struct fbcon_ops *ops = info->fbcon_par;
608 int cnt, erase = vc->vc_video_erase_char, step; 606 int cnt, erase = vc->vc_video_erase_char, step;
609 unsigned short *save = NULL, *r, *q; 607 unsigned short *save = NULL, *r, *q;
608 int logo_height;
610 609
611 if (info->flags & FBINFO_MODULE) { 610 if (info->flags & FBINFO_MODULE) {
612 logo_shown = FBCON_LOGO_DONTSHOW; 611 logo_shown = FBCON_LOGO_DONTSHOW;
@@ -1312,6 +1311,9 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
1312 if (!height || !width) 1311 if (!height || !width)
1313 return; 1312 return;
1314 1313
1314 if (sy < vc->vc_top && vc->vc_top == logo_lines)
1315 vc->vc_top = 0;
1316
1315 /* Split blits that cross physical y_wrap boundary */ 1317 /* Split blits that cross physical y_wrap boundary */
1316 1318
1317 y_break = p->vrows - p->yscroll; 1319 y_break = p->vrows - p->yscroll;
@@ -1853,8 +1855,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
1853 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1855 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
1854 struct display *p = &fb_display[vc->vc_num]; 1856 struct display *p = &fb_display[vc->vc_num];
1855 int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; 1857 int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
1856 unsigned short saved_ec;
1857 int ret;
1858 1858
1859 if (fbcon_is_inactive(vc, info)) 1859 if (fbcon_is_inactive(vc, info))
1860 return -EINVAL; 1860 return -EINVAL;
@@ -1867,11 +1867,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
1867 * whole screen (prevents flicker). 1867 * whole screen (prevents flicker).
1868 */ 1868 */
1869 1869
1870 saved_ec = vc->vc_video_erase_char;
1871 vc->vc_video_erase_char = vc->vc_scrl_erase_char;
1872
1873 ret = 0;
1874
1875 switch (dir) { 1870 switch (dir) {
1876 case SM_UP: 1871 case SM_UP:
1877 if (count > vc->vc_rows) /* Maximum realistic size */ 1872 if (count > vc->vc_rows) /* Maximum realistic size */
@@ -1888,9 +1883,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
1888 scr_memsetw((unsigned short *) (vc->vc_origin + 1883 scr_memsetw((unsigned short *) (vc->vc_origin +
1889 vc->vc_size_row * 1884 vc->vc_size_row *
1890 (b - count)), 1885 (b - count)),
1891 vc->vc_scrl_erase_char, 1886 vc->vc_video_erase_char,
1892 vc->vc_size_row * count); 1887 vc->vc_size_row * count);
1893 ret = 1; 1888 return 1;
1894 break; 1889 break;
1895 1890
1896 case SCROLL_WRAP_MOVE: 1891 case SCROLL_WRAP_MOVE:
@@ -1960,10 +1955,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
1960 scr_memsetw((unsigned short *) (vc->vc_origin + 1955 scr_memsetw((unsigned short *) (vc->vc_origin +
1961 vc->vc_size_row * 1956 vc->vc_size_row *
1962 (b - count)), 1957 (b - count)),
1963 vc->vc_scrl_erase_char, 1958 vc->vc_video_erase_char,
1964 vc->vc_size_row * count); 1959 vc->vc_size_row * count);
1965 ret = 1; 1960 return 1;
1966 break;
1967 } 1961 }
1968 break; 1962 break;
1969 1963
@@ -1980,9 +1974,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
1980 scr_memsetw((unsigned short *) (vc->vc_origin + 1974 scr_memsetw((unsigned short *) (vc->vc_origin +
1981 vc->vc_size_row * 1975 vc->vc_size_row *
1982 t), 1976 t),
1983 vc->vc_scrl_erase_char, 1977 vc->vc_video_erase_char,
1984 vc->vc_size_row * count); 1978 vc->vc_size_row * count);
1985 ret = 1; 1979 return 1;
1986 break; 1980 break;
1987 1981
1988 case SCROLL_WRAP_MOVE: 1982 case SCROLL_WRAP_MOVE:
@@ -2050,15 +2044,12 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
2050 scr_memsetw((unsigned short *) (vc->vc_origin + 2044 scr_memsetw((unsigned short *) (vc->vc_origin +
2051 vc->vc_size_row * 2045 vc->vc_size_row *
2052 t), 2046 t),
2053 vc->vc_scrl_erase_char, 2047 vc->vc_video_erase_char,
2054 vc->vc_size_row * count); 2048 vc->vc_size_row * count);
2055 ret = 1; 2049 return 1;
2056 break;
2057 } 2050 }
2058 break;
2059 } 2051 }
2060 vc->vc_video_erase_char = saved_ec; 2052 return 0;
2061 return ret;
2062} 2053}
2063 2054
2064 2055
@@ -2398,11 +2389,15 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
2398 2389
2399 if (!fbcon_is_inactive(vc, info)) { 2390 if (!fbcon_is_inactive(vc, info)) {
2400 if (ops->blank_state != blank) { 2391 if (ops->blank_state != blank) {
2392 int ret = 1;
2393
2401 ops->blank_state = blank; 2394 ops->blank_state = blank;
2402 fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); 2395 fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
2403 ops->cursor_flash = (!blank); 2396 ops->cursor_flash = (!blank);
2404 2397
2405 if (fb_blank(info, blank)) 2398 if (info->fbops->fb_blank)
2399 ret = info->fbops->fb_blank(blank, info);
2400 if (ret)
2406 fbcon_generic_blank(vc, info, blank); 2401 fbcon_generic_blank(vc, info, blank);
2407 } 2402 }
2408 2403
@@ -2516,9 +2511,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2516 c = vc->vc_video_erase_char; 2511 c = vc->vc_video_erase_char;
2517 vc->vc_video_erase_char = 2512 vc->vc_video_erase_char =
2518 ((c & 0xfe00) >> 1) | (c & 0xff); 2513 ((c & 0xfe00) >> 1) | (c & 0xff);
2519 c = vc->vc_def_color;
2520 vc->vc_scrl_erase_char =
2521 ((c & 0xFE00) >> 1) | (c & 0xFF);
2522 vc->vc_attr >>= 1; 2514 vc->vc_attr >>= 1;
2523 } 2515 }
2524 } else if (!vc->vc_hi_font_mask && cnt == 512) { 2516 } else if (!vc->vc_hi_font_mask && cnt == 512) {
@@ -2549,14 +2541,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2549 if (vc->vc_can_do_color) { 2541 if (vc->vc_can_do_color) {
2550 vc->vc_video_erase_char = 2542 vc->vc_video_erase_char =
2551 ((c & 0xff00) << 1) | (c & 0xff); 2543 ((c & 0xff00) << 1) | (c & 0xff);
2552 c = vc->vc_def_color;
2553 vc->vc_scrl_erase_char =
2554 ((c & 0xFF00) << 1) | (c & 0xFF);
2555 vc->vc_attr <<= 1; 2544 vc->vc_attr <<= 1;
2556 } else { 2545 } else
2557 vc->vc_video_erase_char = c & ~0x100; 2546 vc->vc_video_erase_char = c & ~0x100;
2558 vc->vc_scrl_erase_char = c & ~0x100;
2559 }
2560 } 2547 }
2561 2548
2562 } 2549 }
@@ -2990,8 +2977,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
2990 p = &fb_display[vc->vc_num]; 2977 p = &fb_display[vc->vc_num];
2991 set_blitting_type(vc, info); 2978 set_blitting_type(vc, info);
2992 var_to_display(p, &info->var, info); 2979 var_to_display(p, &info->var, info);
2993 cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres); 2980 cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
2994 rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres); 2981 rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2995 cols /= vc->vc_font.width; 2982 cols /= vc->vc_font.width;
2996 rows /= vc->vc_font.height; 2983 rows /= vc->vc_font.height;
2997 vc_resize(vc, cols, rows); 2984 vc_resize(vc, cols, rows);
@@ -3586,7 +3573,8 @@ static int __init fb_console_init(void)
3586 3573
3587 acquire_console_sem(); 3574 acquire_console_sem();
3588 fb_register_client(&fbcon_event_notifier); 3575 fb_register_client(&fbcon_event_notifier);
3589 fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon"); 3576 fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
3577 "fbcon");
3590 3578
3591 if (IS_ERR(fbcon_device)) { 3579 if (IS_ERR(fbcon_device)) {
3592 printk(KERN_WARNING "Unable to create device " 3580 printk(KERN_WARNING "Unable to create device "
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 0135e0395456..89a346880ec0 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -110,7 +110,7 @@ static inline int mono_col(const struct fb_info *info)
110 __u32 max_len; 110 __u32 max_len;
111 max_len = max(info->var.green.length, info->var.red.length); 111 max_len = max(info->var.green.length, info->var.red.length);
112 max_len = max(info->var.blue.length, max_len); 112 max_len = max(info->var.blue.length, max_len);
113 return ~(0xfff << (max_len & 0xff)); 113 return (~(0xfff << max_len)) & 0xff;
114} 114}
115 115
116static inline int attr_col_ec(int shift, struct vc_data *vc, 116static inline int attr_col_ec(int shift, struct vc_data *vc,
@@ -146,10 +146,8 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
146 return is_fg ? fg : bg; 146 return is_fg ? fg : bg;
147} 147}
148 148
149#define attr_bgcol_ec(bgshift,vc,info) \ 149#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0)
150 attr_col_ec(bgshift,vc,info,0); 150#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1)
151#define attr_fgcol_ec(fgshift,vc,info) \
152 attr_col_ec(fgshift,vc,info,1);
153 151
154/* Font */ 152/* Font */
155#define REFCOUNT(fd) (((int *)(fd))[-1]) 153#define REFCOUNT(fd) (((int *)(fd))[-1])
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 38a296bbdfc9..dd3eaaad4441 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -71,13 +71,15 @@ static char *mda_type_name;
71 71
72/* console information */ 72/* console information */
73 73
74static int mda_first_vc = 1; 74static int mda_first_vc = 13;
75static int mda_last_vc = 16; 75static int mda_last_vc = 16;
76 76
77static struct vc_data *mda_display_fg = NULL; 77static struct vc_data *mda_display_fg = NULL;
78 78
79module_param(mda_first_vc, int, 0); 79module_param(mda_first_vc, int, 0);
80MODULE_PARM_DESC(mda_first_vc, "First virtual console. Default: 13");
80module_param(mda_last_vc, int, 0); 81module_param(mda_last_vc, int, 0);
82MODULE_PARM_DESC(mda_last_vc, "Last virtual console. Default: 16");
81 83
82/* MDA register values 84/* MDA register values
83 */ 85 */
@@ -531,7 +533,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
531 533
532static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) 534static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
533{ 535{
534 u16 eattr = mda_convert_attr(c->vc_scrl_erase_char); 536 u16 eattr = mda_convert_attr(c->vc_video_erase_char);
535 537
536 if (!lines) 538 if (!lines)
537 return 0; 539 return 0;
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index a11cc2fdd4cd..491c1c1baf4c 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
170 switch (dir) { 170 switch (dir) {
171 case SM_UP: 171 case SM_UP:
172 sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols); 172 sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
173 sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char); 173 sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
174 break; 174 break;
175 175
176 case SM_DOWN: 176 case SM_DOWN:
177 sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols); 177 sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
178 sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char); 178 sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
179 break; 179 break;
180 } 180 }
181 181
@@ -370,7 +370,7 @@ static const struct consw sti_con = {
370 370
371 371
372 372
373int __init sticonsole_init(void) 373static int __init sticonsole_init(void)
374{ 374{
375 /* already initialized ? */ 375 /* already initialized ? */
376 if (sticon_sti) 376 if (sticon_sti)
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index e9ab657f0bb7..ef7870f5ea08 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -24,12 +24,13 @@
24#include <asm/hardware.h> 24#include <asm/hardware.h>
25#include <asm/parisc-device.h> 25#include <asm/parisc-device.h>
26#include <asm/cacheflush.h> 26#include <asm/cacheflush.h>
27#include <asm/grfioctl.h>
27 28
28#include "../sticore.h" 29#include "../sticore.h"
29 30
30#define STI_DRIVERVERSION "Version 0.9a" 31#define STI_DRIVERVERSION "Version 0.9a"
31 32
32struct sti_struct *default_sti __read_mostly; 33static struct sti_struct *default_sti __read_mostly;
33 34
34/* number of STI ROMS found and their ptrs to each struct */ 35/* number of STI ROMS found and their ptrs to each struct */
35static int num_sti_roms __read_mostly; 36static int num_sti_roms __read_mostly;
@@ -68,8 +69,7 @@ static const struct sti_init_flags default_init_flags = {
68 .init_cmap_tx = 1, 69 .init_cmap_tx = 1,
69}; 70};
70 71
71int 72static int sti_init_graph(struct sti_struct *sti)
72sti_init_graph(struct sti_struct *sti)
73{ 73{
74 struct sti_init_inptr_ext inptr_ext = { 0, }; 74 struct sti_init_inptr_ext inptr_ext = { 0, };
75 struct sti_init_inptr inptr = { 75 struct sti_init_inptr inptr = {
@@ -100,8 +100,7 @@ static const struct sti_conf_flags default_conf_flags = {
100 .wait = STI_WAIT, 100 .wait = STI_WAIT,
101}; 101};
102 102
103void 103static void sti_inq_conf(struct sti_struct *sti)
104sti_inq_conf(struct sti_struct *sti)
105{ 104{
106 struct sti_conf_inptr inptr = { 0, }; 105 struct sti_conf_inptr inptr = { 0, };
107 unsigned long flags; 106 unsigned long flags;
@@ -237,8 +236,8 @@ static void sti_flush(unsigned long start, unsigned long end)
237 flush_icache_range(start, end); 236 flush_icache_range(start, end);
238} 237}
239 238
240void __devinit 239static void __devinit sti_rom_copy(unsigned long base, unsigned long count,
241sti_rom_copy(unsigned long base, unsigned long count, void *dest) 240 void *dest)
242{ 241{
243 unsigned long dest_start = (unsigned long) dest; 242 unsigned long dest_start = (unsigned long) dest;
244 243
@@ -478,8 +477,8 @@ sti_init_glob_cfg(struct sti_struct *sti,
478} 477}
479 478
480#ifdef CONFIG_FB 479#ifdef CONFIG_FB
481struct sti_cooked_font * __devinit 480static struct sti_cooked_font __devinit
482sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) 481*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
483{ 482{
484 const struct font_desc *fbfont; 483 const struct font_desc *fbfont;
485 unsigned int size, bpc; 484 unsigned int size, bpc;
@@ -534,16 +533,16 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
534 return cooked_font; 533 return cooked_font;
535} 534}
536#else 535#else
537struct sti_cooked_font * __devinit 536static struct sti_cooked_font __devinit
538sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) 537*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
539{ 538{
540 return NULL; 539 return NULL;
541} 540}
542#endif 541#endif
543 542
544struct sti_cooked_font * __devinit 543static struct sti_cooked_font __devinit
545sti_select_font(struct sti_cooked_rom *rom, 544*sti_select_font(struct sti_cooked_rom *rom,
546 int (*search_font_fnc) (struct sti_cooked_rom *,int,int) ) 545 int (*search_font_fnc)(struct sti_cooked_rom *, int, int))
547{ 546{
548 struct sti_cooked_font *font; 547 struct sti_cooked_font *font;
549 int i; 548 int i;
@@ -707,8 +706,7 @@ sti_get_bmode_rom (unsigned long address)
707 return raw; 706 return raw;
708} 707}
709 708
710struct sti_rom * __devinit 709static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address)
711sti_get_wmode_rom (unsigned long address)
712{ 710{
713 struct sti_rom *raw; 711 struct sti_rom *raw;
714 unsigned long size; 712 unsigned long size;
@@ -723,11 +721,12 @@ sti_get_wmode_rom (unsigned long address)
723 return raw; 721 return raw;
724} 722}
725 723
726int __devinit 724static int __devinit sti_read_rom(int wordmode, struct sti_struct *sti,
727sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address) 725 unsigned long address)
728{ 726{
729 struct sti_cooked_rom *cooked; 727 struct sti_cooked_rom *cooked;
730 struct sti_rom *raw = NULL; 728 struct sti_rom *raw = NULL;
729 unsigned long revno;
731 730
732 cooked = kmalloc(sizeof *cooked, GFP_KERNEL); 731 cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
733 if (!cooked) 732 if (!cooked)
@@ -770,9 +769,35 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
770 sti->graphics_id[1] = raw->graphics_id[1]; 769 sti->graphics_id[1] = raw->graphics_id[1];
771 770
772 sti_dump_rom(raw); 771 sti_dump_rom(raw);
773 772
773 /* check if the ROM routines in this card are compatible */
774 if (wordmode || sti->graphics_id[1] != 0x09A02587)
775 goto ok;
776
777 revno = (raw->revno[0] << 8) | raw->revno[1];
778
779 switch (sti->graphics_id[0]) {
780 case S9000_ID_HCRX:
781 /* HyperA or HyperB ? */
782 if (revno == 0x8408 || revno == 0x840b)
783 goto msg_not_supported;
784 break;
785 case CRT_ID_THUNDER:
786 if (revno == 0x8509)
787 goto msg_not_supported;
788 break;
789 case CRT_ID_THUNDER2:
790 if (revno == 0x850c)
791 goto msg_not_supported;
792 }
793ok:
774 return 1; 794 return 1;
775 795
796msg_not_supported:
797 printk(KERN_ERR "Sorry, this GSC/STI card is not yet supported.\n");
798 printk(KERN_ERR "Please see http://parisc-linux.org/faq/"
799 "graphics-howto.html for more info.\n");
800 /* fall through */
776out_err: 801out_err:
777 kfree(raw); 802 kfree(raw);
778 kfree(cooked); 803 kfree(cooked);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index bd1f57b259d9..448d209a0bf2 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -239,8 +239,7 @@ static void vgacon_restore_screen(struct vc_data *c)
239 239
240static int vgacon_scrolldelta(struct vc_data *c, int lines) 240static int vgacon_scrolldelta(struct vc_data *c, int lines)
241{ 241{
242 int start, end, count, soff, diff; 242 int start, end, count, soff;
243 void *d, *s;
244 243
245 if (!lines) { 244 if (!lines) {
246 c->vc_visible_origin = c->vc_origin; 245 c->vc_visible_origin = c->vc_origin;
@@ -287,29 +286,29 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
287 if (count > c->vc_rows) 286 if (count > c->vc_rows)
288 count = c->vc_rows; 287 count = c->vc_rows;
289 288
290 diff = c->vc_rows - count; 289 if (count) {
290 int copysize;
291 291
292 d = (void *) c->vc_origin; 292 int diff = c->vc_rows - count;
293 s = (void *) c->vc_screenbuf; 293 void *d = (void *) c->vc_origin;
294 void *s = (void *) c->vc_screenbuf;
294 295
295 while (count--) { 296 count *= c->vc_size_row;
296 scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row); 297 /* how much memory to end of buffer left? */
297 d += c->vc_size_row; 298 copysize = min(count, vgacon_scrollback_size - soff);
298 soff += c->vc_size_row; 299 scr_memcpyw(d, vgacon_scrollback + soff, copysize);
300 d += copysize;
301 count -= copysize;
299 302
300 if (soff >= vgacon_scrollback_size) 303 if (count) {
301 soff = 0; 304 scr_memcpyw(d, vgacon_scrollback, count);
302 } 305 d += count;
306 }
303 307
304 if (diff == c->vc_rows) { 308 if (diff)
309 scr_memcpyw(d, s, diff * c->vc_size_row);
310 } else
305 vgacon_cursor(c, CM_MOVE); 311 vgacon_cursor(c, CM_MOVE);
306 } else {
307 while (diff--) {
308 scr_memcpyw(d, s, c->vc_size_row);
309 d += c->vc_size_row;
310 s += c->vc_size_row;
311 }
312 }
313 312
314 return 1; 313 return 1;
315} 314}
@@ -1350,7 +1349,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1350 } else 1349 } else
1351 c->vc_origin += delta; 1350 c->vc_origin += delta;
1352 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size - 1351 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
1353 delta), c->vc_scrl_erase_char, 1352 delta), c->vc_video_erase_char,
1354 delta); 1353 delta);
1355 } else { 1354 } else {
1356 if (oldo - delta < vga_vram_base) { 1355 if (oldo - delta < vga_vram_base) {
@@ -1363,7 +1362,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1363 } else 1362 } else
1364 c->vc_origin -= delta; 1363 c->vc_origin -= delta;
1365 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; 1364 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
1366 scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char, 1365 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
1367 delta); 1366 delta);
1368 } 1367 }
1369 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; 1368 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index d0e4cb618269..41d62632dcdb 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1425,7 +1425,7 @@ static void cyberpro_common_resume(struct cfb_info *cfb)
1425 1425
1426#ifdef CONFIG_ARCH_SHARK 1426#ifdef CONFIG_ARCH_SHARK
1427 1427
1428#include <asm/arch/hardware.h> 1428#include <mach/hardware.h>
1429 1429
1430static int __devinit cyberpro_vl_probe(void) 1430static int __devinit cyberpro_vl_probe(void)
1431{ 1431{
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
index 6ef800bdf482..4830b1bf51e5 100644
--- a/drivers/video/display/display-sysfs.c
+++ b/drivers/video/display/display-sysfs.c
@@ -153,12 +153,9 @@ struct display_device *display_device_register(struct display_driver *driver,
153 mutex_unlock(&allocated_dsp_lock); 153 mutex_unlock(&allocated_dsp_lock);
154 154
155 if (!ret) { 155 if (!ret) {
156 new_dev->dev = device_create_drvdata(display_class, 156 new_dev->dev = device_create(display_class, parent,
157 parent, 157 MKDEV(0, 0), new_dev,
158 MKDEV(0,0), 158 "display%d", new_dev->idx);
159 new_dev,
160 "display%d",
161 new_dev->idx);
162 if (!IS_ERR(new_dev->dev)) { 159 if (!IS_ERR(new_dev->dev)) {
163 new_dev->parent = parent; 160 new_dev->parent = parent;
164 new_dev->driver = driver; 161 new_dev->driver = driver;
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index bd779ae44b1e..daf9b81878a4 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -12,6 +12,7 @@
12#include <linux/fb.h> 12#include <linux/fb.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/screen_info.h> 14#include <linux/screen_info.h>
15#include <linux/dmi.h>
15 16
16#include <video/vga.h> 17#include <video/vga.h>
17 18
@@ -33,6 +34,105 @@ static struct fb_fix_screeninfo efifb_fix __initdata = {
33 .visual = FB_VISUAL_TRUECOLOR, 34 .visual = FB_VISUAL_TRUECOLOR,
34}; 35};
35 36
37enum {
38 M_I17, /* 17-Inch iMac */
39 M_I20, /* 20-Inch iMac */
40 M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
41 M_I24, /* 24-Inch iMac */
42 M_MINI, /* Mac Mini */
43 M_MB, /* MacBook */
44 M_MB_2, /* MacBook, 2nd rev. */
45 M_MB_3, /* MacBook, 3rd rev. */
46 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
47 M_MBA, /* MacBook Air */
48 M_MBP, /* MacBook Pro */
49 M_MBP_2, /* MacBook Pro 2nd gen */
50 M_MBP_SR, /* MacBook Pro (Santa Rosa) */
51 M_MBP_4, /* MacBook Pro, 4th gen */
52 M_UNKNOWN /* placeholder */
53};
54
55static struct efifb_dmi_info {
56 char *optname;
57 unsigned long base;
58 int stride;
59 int width;
60 int height;
61} dmi_list[] = {
62 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
63 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
64 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
65 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
66 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
67 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
68 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
69 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
70 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
71 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
72 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
73 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
74};
75
76static int set_system(const struct dmi_system_id *id);
77
78#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
79 { set_system, name, { \
80 DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
81 DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
82 &dmi_list[enumid] }
83
84static struct dmi_system_id __initdata dmi_system_table[] = {
85 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
86 /* At least one of these two will be right; maybe both? */
87 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
88 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
89 /* At least one of these two will be right; maybe both? */
90 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
91 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
92 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
93 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
94 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
95 /* At least one of these two will be right; maybe both? */
96 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
97 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
98 /* At least one of these two will be right; maybe both? */
99 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
100 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
101 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
102 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
103 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
104 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
105 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
106 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
107 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
108 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
109 {},
110};
111
112static int set_system(const struct dmi_system_id *id)
113{
114 struct efifb_dmi_info *info = id->driver_data;
115 if (info->base == 0)
116 return -ENODEV;
117
118 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
119 "(%dx%d, stride %d)\n", id->ident,
120 (void *)info->base, info->width, info->height,
121 info->stride);
122
123 /* Trust the bootloader over the DMI tables */
124 if (screen_info.lfb_base == 0)
125 screen_info.lfb_base = info->base;
126 if (screen_info.lfb_linelength == 0)
127 screen_info.lfb_linelength = info->stride;
128 if (screen_info.lfb_width == 0)
129 screen_info.lfb_width = info->width;
130 if (screen_info.lfb_height == 0)
131 screen_info.lfb_height = info->height;
132
133 return 0;
134}
135
36static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, 136static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
37 unsigned blue, unsigned transp, 137 unsigned blue, unsigned transp,
38 struct fb_info *info) 138 struct fb_info *info)
@@ -67,6 +167,38 @@ static struct fb_ops efifb_ops = {
67 .fb_imageblit = cfb_imageblit, 167 .fb_imageblit = cfb_imageblit,
68}; 168};
69 169
170static int __init efifb_setup(char *options)
171{
172 char *this_opt;
173 int i;
174
175 if (!options || !*options)
176 return 0;
177
178 while ((this_opt = strsep(&options, ",")) != NULL) {
179 if (!*this_opt) continue;
180
181 for (i = 0; i < M_UNKNOWN; i++) {
182 if (!strcmp(this_opt, dmi_list[i].optname) &&
183 dmi_list[i].base != 0) {
184 screen_info.lfb_base = dmi_list[i].base;
185 screen_info.lfb_linelength = dmi_list[i].stride;
186 screen_info.lfb_width = dmi_list[i].width;
187 screen_info.lfb_height = dmi_list[i].height;
188 }
189 }
190 if (!strncmp(this_opt, "base:", 5))
191 screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
192 else if (!strncmp(this_opt, "stride:", 7))
193 screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
194 else if (!strncmp(this_opt, "height:", 7))
195 screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
196 else if (!strncmp(this_opt, "width:", 6))
197 screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
198 }
199 return 0;
200}
201
70static int __init efifb_probe(struct platform_device *dev) 202static int __init efifb_probe(struct platform_device *dev)
71{ 203{
72 struct fb_info *info; 204 struct fb_info *info;
@@ -74,6 +206,26 @@ static int __init efifb_probe(struct platform_device *dev)
74 unsigned int size_vmode; 206 unsigned int size_vmode;
75 unsigned int size_remap; 207 unsigned int size_remap;
76 unsigned int size_total; 208 unsigned int size_total;
209 int request_succeeded = 0;
210
211 printk(KERN_INFO "efifb: probing for efifb\n");
212
213 if (!screen_info.lfb_depth)
214 screen_info.lfb_depth = 32;
215 if (!screen_info.pages)
216 screen_info.pages = 1;
217
218 /* just assume they're all unset if any are */
219 if (!screen_info.blue_size) {
220 screen_info.blue_size = 8;
221 screen_info.blue_pos = 0;
222 screen_info.green_size = 8;
223 screen_info.green_pos = 8;
224 screen_info.red_size = 8;
225 screen_info.red_pos = 16;
226 screen_info.rsvd_size = 8;
227 screen_info.rsvd_pos = 24;
228 }
77 229
78 efifb_fix.smem_start = screen_info.lfb_base; 230 efifb_fix.smem_start = screen_info.lfb_base;
79 efifb_defined.bits_per_pixel = screen_info.lfb_depth; 231 efifb_defined.bits_per_pixel = screen_info.lfb_depth;
@@ -98,21 +250,25 @@ static int __init efifb_probe(struct platform_device *dev)
98 * option to simply use size_total as that 250 * option to simply use size_total as that
99 * wastes plenty of kernel address space. */ 251 * wastes plenty of kernel address space. */
100 size_remap = size_vmode * 2; 252 size_remap = size_vmode * 2;
101 if (size_remap < size_vmode)
102 size_remap = size_vmode;
103 if (size_remap > size_total) 253 if (size_remap > size_total)
104 size_remap = size_total; 254 size_remap = size_total;
255 if (size_remap % PAGE_SIZE)
256 size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
105 efifb_fix.smem_len = size_remap; 257 efifb_fix.smem_len = size_remap;
106 258
107 if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb")) 259 if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
260 request_succeeded = 1;
261 } else {
108 /* We cannot make this fatal. Sometimes this comes from magic 262 /* We cannot make this fatal. Sometimes this comes from magic
109 spaces our resource handlers simply don't know about */ 263 spaces our resource handlers simply don't know about */
110 printk(KERN_WARNING 264 printk(KERN_WARNING
111 "efifb: cannot reserve video memory at 0x%lx\n", 265 "efifb: cannot reserve video memory at 0x%lx\n",
112 efifb_fix.smem_start); 266 efifb_fix.smem_start);
267 }
113 268
114 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); 269 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
115 if (!info) { 270 if (!info) {
271 printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
116 err = -ENOMEM; 272 err = -ENOMEM;
117 goto err_release_mem; 273 goto err_release_mem;
118 } 274 }
@@ -125,7 +281,7 @@ static int __init efifb_probe(struct platform_device *dev)
125 "0x%x @ 0x%lx\n", 281 "0x%x @ 0x%lx\n",
126 efifb_fix.smem_len, efifb_fix.smem_start); 282 efifb_fix.smem_len, efifb_fix.smem_start);
127 err = -EIO; 283 err = -EIO;
128 goto err_unmap; 284 goto err_release_fb;
129 } 285 }
130 286
131 printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, " 287 printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
@@ -178,25 +334,27 @@ static int __init efifb_probe(struct platform_device *dev)
178 info->fix = efifb_fix; 334 info->fix = efifb_fix;
179 info->flags = FBINFO_FLAG_DEFAULT; 335 info->flags = FBINFO_FLAG_DEFAULT;
180 336
181 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 337 if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
182 err = -ENOMEM; 338 printk(KERN_ERR "efifb: cannot allocate colormap\n");
183 goto err_unmap; 339 goto err_unmap;
184 } 340 }
185 if (register_framebuffer(info) < 0) { 341 if ((err = register_framebuffer(info)) < 0) {
186 err = -EINVAL; 342 printk(KERN_ERR "efifb: cannot register framebuffer\n");
187 goto err_fb_dealoc; 343 goto err_fb_dealoc;
188 } 344 }
189 printk(KERN_INFO "fb%d: %s frame buffer device\n", 345 printk(KERN_INFO "fb%d: %s frame buffer device\n",
190 info->node, info->fix.id); 346 info->node, info->fix.id);
191 return 0; 347 return 0;
192 348
193err_fb_dealoc: 349err_fb_dealoc:
194 fb_dealloc_cmap(&info->cmap); 350 fb_dealloc_cmap(&info->cmap);
195err_unmap: 351err_unmap:
196 iounmap(info->screen_base); 352 iounmap(info->screen_base);
353err_release_fb:
197 framebuffer_release(info); 354 framebuffer_release(info);
198err_release_mem: 355err_release_mem:
199 release_mem_region(efifb_fix.smem_start, size_total); 356 if (request_succeeded)
357 release_mem_region(efifb_fix.smem_start, size_total);
200 return err; 358 return err;
201} 359}
202 360
@@ -214,9 +372,22 @@ static struct platform_device efifb_device = {
214static int __init efifb_init(void) 372static int __init efifb_init(void)
215{ 373{
216 int ret; 374 int ret;
375 char *option = NULL;
217 376
218 if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) 377 if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
219 return -ENODEV; 378 return -ENODEV;
379 dmi_check_system(dmi_system_table);
380
381 if (fb_get_options("efifb", &option))
382 return -ENODEV;
383 efifb_setup(option);
384
385 /* We don't get linelength from UGA Draw Protocol, only from
386 * EFI Graphics Protocol. So if it's not in DMI, and it's not
387 * passed in from the user, we really can't use the framebuffer.
388 */
389 if (!screen_info.lfb_linelength)
390 return -ENODEV;
220 391
221 ret = platform_driver_register(&efifb_driver); 392 ret = platform_driver_register(&efifb_driver);
222 393
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index cc2810ef5de5..2735b79e52a1 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -71,7 +71,7 @@ struct epson1355_par {
71#if defined(CONFIG_ARM) 71#if defined(CONFIG_ARM)
72 72
73# ifdef CONFIG_ARCH_CEIVA 73# ifdef CONFIG_ARCH_CEIVA
74# include <asm/arch/hardware.h> 74# include <mach/hardware.h>
75# define EPSON1355FB_BASE_PHYS (CEIVA_PHYS_SED1355) 75# define EPSON1355FB_BASE_PHYS (CEIVA_PHYS_SED1355)
76# endif 76# endif
77 77
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 59df132cc375..4835bdc4e9f1 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = {
114 .page_mkwrite = fb_deferred_io_mkwrite, 114 .page_mkwrite = fb_deferred_io_mkwrite,
115}; 115};
116 116
117static int fb_deferred_io_set_page_dirty(struct page *page)
118{
119 if (!PageDirty(page))
120 SetPageDirty(page);
121 return 0;
122}
123
124static const struct address_space_operations fb_deferred_io_aops = {
125 .set_page_dirty = fb_deferred_io_set_page_dirty,
126};
127
117static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) 128static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
118{ 129{
119 vma->vm_ops = &fb_deferred_io_vm_ops; 130 vma->vm_ops = &fb_deferred_io_vm_ops;
@@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info)
163} 174}
164EXPORT_SYMBOL_GPL(fb_deferred_io_init); 175EXPORT_SYMBOL_GPL(fb_deferred_io_init);
165 176
177void fb_deferred_io_open(struct fb_info *info,
178 struct inode *inode,
179 struct file *file)
180{
181 file->f_mapping->a_ops = &fb_deferred_io_aops;
182}
183EXPORT_SYMBOL_GPL(fb_deferred_io_open);
184
166void fb_deferred_io_cleanup(struct fb_info *info) 185void fb_deferred_io_cleanup(struct fb_info *info)
167{ 186{
168 void *screen_base = (void __force *) info->screen_base; 187 void *screen_base = (void __force *) info->screen_base;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 33ebdb198daf..cd5f20da738a 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -28,9 +28,7 @@
28#include <linux/proc_fs.h> 28#include <linux/proc_fs.h>
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/console.h> 30#include <linux/console.h>
31#ifdef CONFIG_KMOD
32#include <linux/kmod.h> 31#include <linux/kmod.h>
33#endif
34#include <linux/err.h> 32#include <linux/err.h>
35#include <linux/device.h> 33#include <linux/device.h>
36#include <linux/efi.h> 34#include <linux/efi.h>
@@ -837,20 +835,12 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
837 return (cnt) ? cnt : err; 835 return (cnt) ? cnt : err;
838} 836}
839 837
840#ifdef CONFIG_KMOD
841static void try_to_load(int fb)
842{
843 request_module("fb%d", fb);
844}
845#endif /* CONFIG_KMOD */
846
847int 838int
848fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) 839fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
849{ 840{
850 struct fb_fix_screeninfo *fix = &info->fix; 841 struct fb_fix_screeninfo *fix = &info->fix;
851 int xoffset = var->xoffset; 842 unsigned int yres = info->var.yres;
852 int yoffset = var->yoffset; 843 int err = 0;
853 int err = 0, yres = info->var.yres;
854 844
855 if (var->yoffset > 0) { 845 if (var->yoffset > 0) {
856 if (var->vmode & FB_VMODE_YWRAP) { 846 if (var->vmode & FB_VMODE_YWRAP) {
@@ -866,8 +856,8 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
866 (var->xoffset % fix->xpanstep))) 856 (var->xoffset % fix->xpanstep)))
867 err = -EINVAL; 857 err = -EINVAL;
868 858
869 if (err || !info->fbops->fb_pan_display || xoffset < 0 || 859 if (err || !info->fbops->fb_pan_display ||
870 yoffset < 0 || var->yoffset + yres > info->var.yres_virtual || 860 var->yoffset + yres > info->var.yres_virtual ||
871 var->xoffset + info->var.xres > info->var.xres_virtual) 861 var->xoffset + info->var.xres > info->var.xres_virtual)
872 return -EINVAL; 862 return -EINVAL;
873 863
@@ -980,6 +970,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
980 970
981 info->flags &= ~FBINFO_MISC_USEREVENT; 971 info->flags &= ~FBINFO_MISC_USEREVENT;
982 event.info = info; 972 event.info = info;
973 event.data = &mode;
983 fb_notifier_call_chain(evnt, &event); 974 fb_notifier_call_chain(evnt, &event);
984 } 975 }
985 } 976 }
@@ -1011,103 +1002,132 @@ fb_blank(struct fb_info *info, int blank)
1011 return ret; 1002 return ret;
1012} 1003}
1013 1004
1014static int 1005static long
1015fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 1006fb_ioctl(struct file *file, unsigned int cmd,
1016 unsigned long arg) 1007 unsigned long arg)
1017{ 1008{
1009 struct inode *inode = file->f_path.dentry->d_inode;
1018 int fbidx = iminor(inode); 1010 int fbidx = iminor(inode);
1019 struct fb_info *info = registered_fb[fbidx]; 1011 struct fb_info *info;
1020 struct fb_ops *fb = info->fbops; 1012 struct fb_ops *fb;
1021 struct fb_var_screeninfo var; 1013 struct fb_var_screeninfo var;
1022 struct fb_fix_screeninfo fix; 1014 struct fb_fix_screeninfo fix;
1023 struct fb_con2fbmap con2fb; 1015 struct fb_con2fbmap con2fb;
1024 struct fb_cmap_user cmap; 1016 struct fb_cmap_user cmap;
1025 struct fb_event event; 1017 struct fb_event event;
1026 void __user *argp = (void __user *)arg; 1018 void __user *argp = (void __user *)arg;
1027 int i; 1019 long ret = 0;
1028 1020
1029 if (!fb) 1021 info = registered_fb[fbidx];
1022 mutex_lock(&info->lock);
1023 fb = info->fbops;
1024
1025 if (!fb) {
1026 mutex_unlock(&info->lock);
1030 return -ENODEV; 1027 return -ENODEV;
1028 }
1031 switch (cmd) { 1029 switch (cmd) {
1032 case FBIOGET_VSCREENINFO: 1030 case FBIOGET_VSCREENINFO:
1033 return copy_to_user(argp, &info->var, 1031 ret = copy_to_user(argp, &info->var,
1034 sizeof(var)) ? -EFAULT : 0; 1032 sizeof(var)) ? -EFAULT : 0;
1033 break;
1035 case FBIOPUT_VSCREENINFO: 1034 case FBIOPUT_VSCREENINFO:
1036 if (copy_from_user(&var, argp, sizeof(var))) 1035 if (copy_from_user(&var, argp, sizeof(var))) {
1037 return -EFAULT; 1036 ret = -EFAULT;
1037 break;
1038 }
1038 acquire_console_sem(); 1039 acquire_console_sem();
1039 info->flags |= FBINFO_MISC_USEREVENT; 1040 info->flags |= FBINFO_MISC_USEREVENT;
1040 i = fb_set_var(info, &var); 1041 ret = fb_set_var(info, &var);
1041 info->flags &= ~FBINFO_MISC_USEREVENT; 1042 info->flags &= ~FBINFO_MISC_USEREVENT;
1042 release_console_sem(); 1043 release_console_sem();
1043 if (i) return i; 1044 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
1044 if (copy_to_user(argp, &var, sizeof(var))) 1045 ret = -EFAULT;
1045 return -EFAULT; 1046 break;
1046 return 0;
1047 case FBIOGET_FSCREENINFO: 1047 case FBIOGET_FSCREENINFO:
1048 return copy_to_user(argp, &info->fix, 1048 ret = copy_to_user(argp, &info->fix,
1049 sizeof(fix)) ? -EFAULT : 0; 1049 sizeof(fix)) ? -EFAULT : 0;
1050 break;
1050 case FBIOPUTCMAP: 1051 case FBIOPUTCMAP:
1051 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1052 if (copy_from_user(&cmap, argp, sizeof(cmap)))
1052 return -EFAULT; 1053 ret = -EFAULT;
1053 return (fb_set_user_cmap(&cmap, info)); 1054 else
1055 ret = fb_set_user_cmap(&cmap, info);
1056 break;
1054 case FBIOGETCMAP: 1057 case FBIOGETCMAP:
1055 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1058 if (copy_from_user(&cmap, argp, sizeof(cmap)))
1056 return -EFAULT; 1059 ret = -EFAULT;
1057 return fb_cmap_to_user(&info->cmap, &cmap); 1060 else
1061 ret = fb_cmap_to_user(&info->cmap, &cmap);
1062 break;
1058 case FBIOPAN_DISPLAY: 1063 case FBIOPAN_DISPLAY:
1059 if (copy_from_user(&var, argp, sizeof(var))) 1064 if (copy_from_user(&var, argp, sizeof(var))) {
1060 return -EFAULT; 1065 ret = -EFAULT;
1066 break;
1067 }
1061 acquire_console_sem(); 1068 acquire_console_sem();
1062 i = fb_pan_display(info, &var); 1069 ret = fb_pan_display(info, &var);
1063 release_console_sem(); 1070 release_console_sem();
1064 if (i) 1071 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
1065 return i; 1072 ret = -EFAULT;
1066 if (copy_to_user(argp, &var, sizeof(var))) 1073 break;
1067 return -EFAULT;
1068 return 0;
1069 case FBIO_CURSOR: 1074 case FBIO_CURSOR:
1070 return -EINVAL; 1075 ret = -EINVAL;
1076 break;
1071 case FBIOGET_CON2FBMAP: 1077 case FBIOGET_CON2FBMAP:
1072 if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 1078 if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
1073 return -EFAULT; 1079 ret = -EFAULT;
1074 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 1080 else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
1075 return -EINVAL; 1081 ret = -EINVAL;
1076 con2fb.framebuffer = -1; 1082 else {
1077 event.info = info; 1083 con2fb.framebuffer = -1;
1078 event.data = &con2fb; 1084 event.info = info;
1079 fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); 1085 event.data = &con2fb;
1080 return copy_to_user(argp, &con2fb, 1086 fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
1087 &event);
1088 ret = copy_to_user(argp, &con2fb,
1081 sizeof(con2fb)) ? -EFAULT : 0; 1089 sizeof(con2fb)) ? -EFAULT : 0;
1090 }
1091 break;
1082 case FBIOPUT_CON2FBMAP: 1092 case FBIOPUT_CON2FBMAP:
1083 if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 1093 if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
1084 return - EFAULT; 1094 ret = -EFAULT;
1085 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 1095 break;
1086 return -EINVAL; 1096 }
1087 if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) 1097 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
1088 return -EINVAL; 1098 ret = -EINVAL;
1089#ifdef CONFIG_KMOD 1099 break;
1090 if (!registered_fb[con2fb.framebuffer]) 1100 }
1091 try_to_load(con2fb.framebuffer); 1101 if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
1092#endif /* CONFIG_KMOD */ 1102 ret = -EINVAL;
1103 break;
1104 }
1093 if (!registered_fb[con2fb.framebuffer]) 1105 if (!registered_fb[con2fb.framebuffer])
1094 return -EINVAL; 1106 request_module("fb%d", con2fb.framebuffer);
1107 if (!registered_fb[con2fb.framebuffer]) {
1108 ret = -EINVAL;
1109 break;
1110 }
1095 event.info = info; 1111 event.info = info;
1096 event.data = &con2fb; 1112 event.data = &con2fb;
1097 return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, 1113 ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
1098 &event); 1114 &event);
1115 break;
1099 case FBIOBLANK: 1116 case FBIOBLANK:
1100 acquire_console_sem(); 1117 acquire_console_sem();
1101 info->flags |= FBINFO_MISC_USEREVENT; 1118 info->flags |= FBINFO_MISC_USEREVENT;
1102 i = fb_blank(info, arg); 1119 ret = fb_blank(info, arg);
1103 info->flags &= ~FBINFO_MISC_USEREVENT; 1120 info->flags &= ~FBINFO_MISC_USEREVENT;
1104 release_console_sem(); 1121 release_console_sem();
1105 return i; 1122 break;;
1106 default: 1123 default:
1107 if (fb->fb_ioctl == NULL) 1124 if (fb->fb_ioctl == NULL)
1108 return -EINVAL; 1125 ret = -ENOTTY;
1109 return fb->fb_ioctl(info, cmd, arg); 1126 else
1127 ret = fb->fb_ioctl(info, cmd, arg);
1110 } 1128 }
1129 mutex_unlock(&info->lock);
1130 return ret;
1111} 1131}
1112 1132
1113#ifdef CONFIG_COMPAT 1133#ifdef CONFIG_COMPAT
@@ -1161,7 +1181,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file,
1161 put_user(compat_ptr(data), &cmap->transp)) 1181 put_user(compat_ptr(data), &cmap->transp))
1162 return -EFAULT; 1182 return -EFAULT;
1163 1183
1164 err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); 1184 err = fb_ioctl(file, cmd, (unsigned long) cmap);
1165 1185
1166 if (!err) { 1186 if (!err) {
1167 if (copy_in_user(&cmap32->start, 1187 if (copy_in_user(&cmap32->start,
@@ -1215,7 +1235,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
1215 1235
1216 old_fs = get_fs(); 1236 old_fs = get_fs();
1217 set_fs(KERNEL_DS); 1237 set_fs(KERNEL_DS);
1218 err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); 1238 err = fb_ioctl(file, cmd, (unsigned long) &fix);
1219 set_fs(old_fs); 1239 set_fs(old_fs);
1220 1240
1221 if (!err) 1241 if (!err)
@@ -1233,7 +1253,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1233 struct fb_ops *fb = info->fbops; 1253 struct fb_ops *fb = info->fbops;
1234 long ret = -ENOIOCTLCMD; 1254 long ret = -ENOIOCTLCMD;
1235 1255
1236 lock_kernel(); 1256 mutex_lock(&info->lock);
1237 switch(cmd) { 1257 switch(cmd) {
1238 case FBIOGET_VSCREENINFO: 1258 case FBIOGET_VSCREENINFO:
1239 case FBIOPUT_VSCREENINFO: 1259 case FBIOPUT_VSCREENINFO:
@@ -1242,7 +1262,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1242 case FBIOPUT_CON2FBMAP: 1262 case FBIOPUT_CON2FBMAP:
1243 arg = (unsigned long) compat_ptr(arg); 1263 arg = (unsigned long) compat_ptr(arg);
1244 case FBIOBLANK: 1264 case FBIOBLANK:
1245 ret = fb_ioctl(inode, file, cmd, arg); 1265 ret = fb_ioctl(file, cmd, arg);
1246 break; 1266 break;
1247 1267
1248 case FBIOGET_FSCREENINFO: 1268 case FBIOGET_FSCREENINFO:
@@ -1259,7 +1279,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1259 ret = fb->fb_compat_ioctl(info, cmd, arg); 1279 ret = fb->fb_compat_ioctl(info, cmd, arg);
1260 break; 1280 break;
1261 } 1281 }
1262 unlock_kernel(); 1282 mutex_unlock(&info->lock);
1263 return ret; 1283 return ret;
1264} 1284}
1265#endif 1285#endif
@@ -1281,13 +1301,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1281 return -ENODEV; 1301 return -ENODEV;
1282 if (fb->fb_mmap) { 1302 if (fb->fb_mmap) {
1283 int res; 1303 int res;
1284 lock_kernel(); 1304 mutex_lock(&info->lock);
1285 res = fb->fb_mmap(info, vma); 1305 res = fb->fb_mmap(info, vma);
1286 unlock_kernel(); 1306 mutex_unlock(&info->lock);
1287 return res; 1307 return res;
1288 } 1308 }
1289 1309
1290 lock_kernel(); 1310 mutex_lock(&info->lock);
1291 1311
1292 /* frame buffer memory */ 1312 /* frame buffer memory */
1293 start = info->fix.smem_start; 1313 start = info->fix.smem_start;
@@ -1296,13 +1316,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1296 /* memory mapped io */ 1316 /* memory mapped io */
1297 off -= len; 1317 off -= len;
1298 if (info->var.accel_flags) { 1318 if (info->var.accel_flags) {
1299 unlock_kernel(); 1319 mutex_unlock(&info->lock);
1300 return -EINVAL; 1320 return -EINVAL;
1301 } 1321 }
1302 start = info->fix.mmio_start; 1322 start = info->fix.mmio_start;
1303 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); 1323 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
1304 } 1324 }
1305 unlock_kernel(); 1325 mutex_unlock(&info->lock);
1306 start &= PAGE_MASK; 1326 start &= PAGE_MASK;
1307 if ((vma->vm_end - vma->vm_start + off) > len) 1327 if ((vma->vm_end - vma->vm_start + off) > len)
1308 return -EINVAL; 1328 return -EINVAL;
@@ -1326,15 +1346,13 @@ fb_open(struct inode *inode, struct file *file)
1326 1346
1327 if (fbidx >= FB_MAX) 1347 if (fbidx >= FB_MAX)
1328 return -ENODEV; 1348 return -ENODEV;
1329 lock_kernel(); 1349 info = registered_fb[fbidx];
1330#ifdef CONFIG_KMOD 1350 if (!info)
1331 if (!(info = registered_fb[fbidx])) 1351 request_module("fb%d", fbidx);
1332 try_to_load(fbidx); 1352 info = registered_fb[fbidx];
1333#endif /* CONFIG_KMOD */ 1353 if (!info)
1334 if (!(info = registered_fb[fbidx])) { 1354 return -ENODEV;
1335 res = -ENODEV; 1355 mutex_lock(&info->lock);
1336 goto out;
1337 }
1338 if (!try_module_get(info->fbops->owner)) { 1356 if (!try_module_get(info->fbops->owner)) {
1339 res = -ENODEV; 1357 res = -ENODEV;
1340 goto out; 1358 goto out;
@@ -1345,8 +1363,12 @@ fb_open(struct inode *inode, struct file *file)
1345 if (res) 1363 if (res)
1346 module_put(info->fbops->owner); 1364 module_put(info->fbops->owner);
1347 } 1365 }
1366#ifdef CONFIG_FB_DEFERRED_IO
1367 if (info->fbdefio)
1368 fb_deferred_io_open(info, inode, file);
1369#endif
1348out: 1370out:
1349 unlock_kernel(); 1371 mutex_unlock(&info->lock);
1350 return res; 1372 return res;
1351} 1373}
1352 1374
@@ -1355,11 +1377,11 @@ fb_release(struct inode *inode, struct file *file)
1355{ 1377{
1356 struct fb_info * const info = file->private_data; 1378 struct fb_info * const info = file->private_data;
1357 1379
1358 lock_kernel(); 1380 mutex_lock(&info->lock);
1359 if (info->fbops->fb_release) 1381 if (info->fbops->fb_release)
1360 info->fbops->fb_release(info,1); 1382 info->fbops->fb_release(info,1);
1361 module_put(info->fbops->owner); 1383 module_put(info->fbops->owner);
1362 unlock_kernel(); 1384 mutex_unlock(&info->lock);
1363 return 0; 1385 return 0;
1364} 1386}
1365 1387
@@ -1367,7 +1389,7 @@ static const struct file_operations fb_fops = {
1367 .owner = THIS_MODULE, 1389 .owner = THIS_MODULE,
1368 .read = fb_read, 1390 .read = fb_read,
1369 .write = fb_write, 1391 .write = fb_write,
1370 .ioctl = fb_ioctl, 1392 .unlocked_ioctl = fb_ioctl,
1371#ifdef CONFIG_COMPAT 1393#ifdef CONFIG_COMPAT
1372 .compat_ioctl = fb_compat_ioctl, 1394 .compat_ioctl = fb_compat_ioctl,
1373#endif 1395#endif
@@ -1438,9 +1460,10 @@ register_framebuffer(struct fb_info *fb_info)
1438 if (!registered_fb[i]) 1460 if (!registered_fb[i])
1439 break; 1461 break;
1440 fb_info->node = i; 1462 fb_info->node = i;
1463 mutex_init(&fb_info->lock);
1441 1464
1442 fb_info->dev = device_create(fb_class, fb_info->device, 1465 fb_info->dev = device_create(fb_class, fb_info->device,
1443 MKDEV(FB_MAJOR, i), "fb%d", i); 1466 MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
1444 if (IS_ERR(fb_info->dev)) { 1467 if (IS_ERR(fb_info->dev)) {
1445 /* Not fatal */ 1468 /* Not fatal */
1446 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); 1469 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 052e18058498..5c1a2c01778f 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -564,7 +564,13 @@ static void get_detailed_timing(unsigned char *block,
564 mode->sync |= FB_SYNC_VERT_HIGH_ACT; 564 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
565 mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) * 565 mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
566 (V_ACTIVE + V_BLANKING)); 566 (V_ACTIVE + V_BLANKING));
567 mode->vmode = 0; 567 if (INTERLACED) {
568 mode->yres *= 2;
569 mode->upper_margin *= 2;
570 mode->lower_margin *= 2;
571 mode->vsync_len *= 2;
572 mode->vmode |= FB_VMODE_INTERLACED;
573 }
568 mode->flag = FB_MODE_IS_DETAILED; 574 mode->flag = FB_MODE_IS_DETAILED;
569 575
570 DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000); 576 DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);
@@ -879,7 +885,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
879 if (edid_is_timing_block(block)) { 885 if (edid_is_timing_block(block)) {
880 var->xres = var->xres_virtual = H_ACTIVE; 886 var->xres = var->xres_virtual = H_ACTIVE;
881 var->yres = var->yres_virtual = V_ACTIVE; 887 var->yres = var->yres_virtual = V_ACTIVE;
882 var->height = var->width = -1; 888 var->height = var->width = 0;
883 var->right_margin = H_SYNC_OFFSET; 889 var->right_margin = H_SYNC_OFFSET;
884 var->left_margin = (H_ACTIVE + H_BLANKING) - 890 var->left_margin = (H_ACTIVE + H_BLANKING) -
885 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); 891 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 7992b13ee68f..9dbb9646081f 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -1042,7 +1042,7 @@ static int __devexit ffb_remove(struct of_device *op)
1042 return 0; 1042 return 0;
1043} 1043}
1044 1044
1045static struct of_device_id ffb_match[] = { 1045static const struct of_device_id ffb_match[] = {
1046 { 1046 {
1047 .name = "SUNW,ffb", 1047 .name = "SUNW,ffb",
1048 }, 1048 },
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 09d7e22c6fef..fb51197d1c98 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -279,58 +279,42 @@ static struct diu_hw dr = {
279 279
280static struct diu_pool pool; 280static struct diu_pool pool;
281 281
282/* To allocate memory for framebuffer. First try __get_free_pages(). If it 282/**
283 * fails, try rh_alloc. The reason is __get_free_pages() cannot allocate 283 * fsl_diu_alloc - allocate memory for the DIU
284 * very large memory (more than 4MB). We don't want to allocate all memory 284 * @size: number of bytes to allocate
285 * in rheap since small memory allocation/deallocation will fragment the 285 * @param: returned physical address of memory
286 * rheap and make the furture large allocation fail. 286 *
287 * This function allocates a physically-contiguous block of memory.
287 */ 288 */
288 289static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
289static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
290{ 290{
291 void *virt; 291 void *virt;
292 292
293 pr_debug("size=%lu\n", size); 293 pr_debug("size=%zu\n", size);
294 294
295 virt = (void *)__get_free_pages(GFP_DMA | __GFP_ZERO, get_order(size)); 295 virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
296 if (virt) { 296 if (virt) {
297 *phys = virt_to_phys(virt); 297 *phys = virt_to_phys(virt);
298 pr_debug("virt %p, phys=%llx\n", virt, (uint64_t) *phys); 298 pr_debug("virt=%p phys=%llx\n", virt,
299 return virt; 299 (unsigned long long)*phys);
300 } 300 }
301 if (!diu_ops.diu_mem) {
302 printk(KERN_INFO "%s: no diu_mem."
303 " To reserve more memory, put 'diufb=15M' "
304 "in the command line\n", __func__);
305 return NULL;
306 }
307
308 virt = (void *)rh_alloc(&diu_ops.diu_rh_info, size, "DIU");
309 if (virt) {
310 *phys = virt_to_bus(virt);
311 memset(virt, 0, size);
312 }
313
314 pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys);
315 301
316 return virt; 302 return virt;
317} 303}
318 304
319static void fsl_diu_free(void *p, unsigned long size) 305/**
306 * fsl_diu_free - release DIU memory
307 * @virt: pointer returned by fsl_diu_alloc()
308 * @size: number of bytes allocated by fsl_diu_alloc()
309 *
310 * This function releases memory allocated by fsl_diu_alloc().
311 */
312static void fsl_diu_free(void *virt, size_t size)
320{ 313{
321 pr_debug("p=%p size=%lu\n", p, size); 314 pr_debug("virt=%p size=%zu\n", virt, size);
322
323 if (!p)
324 return;
325 315
326 if ((p >= diu_ops.diu_mem) && 316 if (virt && size)
327 (p < (diu_ops.diu_mem + diu_ops.diu_size))) { 317 free_pages_exact(virt, size);
328 pr_debug("rh\n");
329 rh_free(&diu_ops.diu_rh_info, (unsigned long) p);
330 } else {
331 pr_debug("dma\n");
332 free_pages((unsigned long)p, get_order(size));
333 }
334} 318}
335 319
336static int fsl_diu_enable_panel(struct fb_info *info) 320static int fsl_diu_enable_panel(struct fb_info *info)
@@ -495,6 +479,10 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
495 base_plane_width = machine_data->fsl_diu_info[0]->var.xres; 479 base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
496 base_plane_height = machine_data->fsl_diu_info[0]->var.yres; 480 base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
497 481
482 if (mfbi->x_aoi_d < 0)
483 mfbi->x_aoi_d = 0;
484 if (mfbi->y_aoi_d < 0)
485 mfbi->y_aoi_d = 0;
498 switch (index) { 486 switch (index) {
499 case 0: 487 case 0:
500 if (mfbi->x_aoi_d != 0) 488 if (mfbi->x_aoi_d != 0)
@@ -794,6 +782,22 @@ static void unmap_video_memory(struct fb_info *info)
794} 782}
795 783
796/* 784/*
785 * Using the fb_var_screeninfo in fb_info we set the aoi of this
786 * particular framebuffer. It is a light version of fsl_diu_set_par.
787 */
788static int fsl_diu_set_aoi(struct fb_info *info)
789{
790 struct fb_var_screeninfo *var = &info->var;
791 struct mfb_info *mfbi = info->par;
792 struct diu_ad *ad = mfbi->ad;
793
794 /* AOI should not be greater than display size */
795 ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
796 ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
797 return 0;
798}
799
800/*
797 * Using the fb_var_screeninfo in fb_info we set the resolution of this 801 * Using the fb_var_screeninfo in fb_info we set the resolution of this
798 * particular framebuffer. This function alters the fb_fix_screeninfo stored 802 * particular framebuffer. This function alters the fb_fix_screeninfo stored
799 * in fb_info. It does not alter var in fb_info since we are using that 803 * in fb_info. It does not alter var in fb_info since we are using that
@@ -833,11 +837,11 @@ static int fsl_diu_set_par(struct fb_info *info)
833 diu_ops.get_pixel_format(var->bits_per_pixel, 837 diu_ops.get_pixel_format(var->bits_per_pixel,
834 machine_data->monitor_port); 838 machine_data->monitor_port);
835 ad->addr = cpu_to_le32(info->fix.smem_start); 839 ad->addr = cpu_to_le32(info->fix.smem_start);
836 ad->src_size_g_alpha = cpu_to_le32((var->yres << 12) | 840 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
837 var->xres) | mfbi->g_alpha; 841 var->xres_virtual) | mfbi->g_alpha;
838 /* fix me. AOI should not be greater than display size */ 842 /* AOI should not be greater than display size */
839 ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres); 843 ad->aoi_size = cpu_to_le32((var->yres << 16) | var->xres);
840 ad->offset_xyi = 0; 844 ad->offset_xyi = cpu_to_le32((var->yoffset << 16) | var->xoffset);
841 ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d); 845 ad->offset_xyd = cpu_to_le32((mfbi->y_aoi_d << 16) | mfbi->x_aoi_d);
842 846
843 /* Disable chroma keying function */ 847 /* Disable chroma keying function */
@@ -937,6 +941,8 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var,
937 else 941 else
938 info->var.vmode &= ~FB_VMODE_YWRAP; 942 info->var.vmode &= ~FB_VMODE_YWRAP;
939 943
944 fsl_diu_set_aoi(info);
945
940 return 0; 946 return 0;
941} 947}
942 948
@@ -1005,7 +1011,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
1005 pr_debug("set AOI display offset of index %d to (%d,%d)\n", 1011 pr_debug("set AOI display offset of index %d to (%d,%d)\n",
1006 mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); 1012 mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d);
1007 fsl_diu_check_var(&info->var, info); 1013 fsl_diu_check_var(&info->var, info);
1008 fsl_diu_set_par(info); 1014 fsl_diu_set_aoi(info);
1009 break; 1015 break;
1010 case MFB_GET_AOID: 1016 case MFB_GET_AOID:
1011 aoi_d.x_aoi_d = mfbi->x_aoi_d; 1017 aoi_d.x_aoi_d = mfbi->x_aoi_d;
@@ -1665,8 +1671,10 @@ static int __init fsl_diu_init(void)
1665 } 1671 }
1666 1672
1667 prop = of_get_property(np, "d-cache-size", NULL); 1673 prop = of_get_property(np, "d-cache-size", NULL);
1668 if (prop == NULL) 1674 if (prop == NULL) {
1675 of_node_put(np);
1669 return -ENODEV; 1676 return -ENODEV;
1677 }
1670 1678
1671 /* Freescale PLRU requires 13/8 times the cache size to do a proper 1679 /* Freescale PLRU requires 13/8 times the cache size to do a proper
1672 displacement flush 1680 displacement flush
@@ -1675,8 +1683,10 @@ static int __init fsl_diu_init(void)
1675 coherence_data_size /= 8; 1683 coherence_data_size /= 8;
1676 1684
1677 prop = of_get_property(np, "d-cache-line-size", NULL); 1685 prop = of_get_property(np, "d-cache-line-size", NULL);
1678 if (prop == NULL) 1686 if (prop == NULL) {
1687 of_node_put(np);
1679 return -ENODEV; 1688 return -ENODEV;
1689 }
1680 d_cache_line_size = *prop; 1690 d_cache_line_size = *prop;
1681 1691
1682 of_node_put(np); 1692 of_node_put(np);
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 2e552d5bbb5d..f89c3cce1e0c 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -87,6 +87,8 @@ static int gbe_revision;
87static int ypan, ywrap; 87static int ypan, ywrap;
88 88
89static uint32_t pseudo_palette[16]; 89static uint32_t pseudo_palette[16];
90static uint32_t gbe_cmap[256];
91static int gbe_turned_on; /* 0 turned off, 1 turned on */
90 92
91static char *mode_option __initdata = NULL; 93static char *mode_option __initdata = NULL;
92 94
@@ -208,6 +210,8 @@ void gbe_turn_off(void)
208 int i; 210 int i;
209 unsigned int val, x, y, vpixen_off; 211 unsigned int val, x, y, vpixen_off;
210 212
213 gbe_turned_on = 0;
214
211 /* check if pixel counter is on */ 215 /* check if pixel counter is on */
212 val = gbe->vt_xy; 216 val = gbe->vt_xy;
213 if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1) 217 if (GET_GBE_FIELD(VT_XY, FREEZE, val) == 1)
@@ -371,6 +375,22 @@ static void gbe_turn_on(void)
371 } 375 }
372 if (i == 10000) 376 if (i == 10000)
373 printk(KERN_ERR "gbefb: turn on DMA timed out\n"); 377 printk(KERN_ERR "gbefb: turn on DMA timed out\n");
378
379 gbe_turned_on = 1;
380}
381
382static void gbe_loadcmap(void)
383{
384 int i, j;
385
386 for (i = 0; i < 256; i++) {
387 for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
388 udelay(10);
389 if (j == 1000)
390 printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
391
392 gbe->cmap[i] = gbe_cmap[i];
393 }
374} 394}
375 395
376/* 396/*
@@ -382,6 +402,7 @@ static int gbefb_blank(int blank, struct fb_info *info)
382 switch (blank) { 402 switch (blank) {
383 case FB_BLANK_UNBLANK: /* unblank */ 403 case FB_BLANK_UNBLANK: /* unblank */
384 gbe_turn_on(); 404 gbe_turn_on();
405 gbe_loadcmap();
385 break; 406 break;
386 407
387 case FB_BLANK_NORMAL: /* blank */ 408 case FB_BLANK_NORMAL: /* blank */
@@ -796,16 +817,10 @@ static int gbefb_set_par(struct fb_info *info)
796 gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8); 817 gbe->gmap[i] = (i << 24) | (i << 16) | (i << 8);
797 818
798 /* Initialize the color map */ 819 /* Initialize the color map */
799 for (i = 0; i < 256; i++) { 820 for (i = 0; i < 256; i++)
800 int j; 821 gbe_cmap[i] = (i << 8) | (i << 16) | (i << 24);
801
802 for (j = 0; j < 1000 && gbe->cm_fifo >= 63; j++)
803 udelay(10);
804 if (j == 1000)
805 printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
806 822
807 gbe->cmap[i] = (i << 8) | (i << 16) | (i << 24); 823 gbe_loadcmap();
808 }
809 824
810 return 0; 825 return 0;
811} 826}
@@ -855,14 +870,17 @@ static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,
855 blue >>= 8; 870 blue >>= 8;
856 871
857 if (info->var.bits_per_pixel <= 8) { 872 if (info->var.bits_per_pixel <= 8) {
858 /* wait for the color map FIFO to have a free entry */ 873 gbe_cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
859 for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++) 874 if (gbe_turned_on) {
860 udelay(10); 875 /* wait for the color map FIFO to have a free entry */
861 if (i == 1000) { 876 for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)
862 printk(KERN_ERR "gbefb: cmap FIFO timeout\n"); 877 udelay(10);
863 return 1; 878 if (i == 1000) {
879 printk(KERN_ERR "gbefb: cmap FIFO timeout\n");
880 return 1;
881 }
882 gbe->cmap[regno] = gbe_cmap[regno];
864 } 883 }
865 gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
866 } else if (regno < 16) { 884 } else if (regno < 16) {
867 switch (info->var.bits_per_pixel) { 885 switch (info->var.bits_per_pixel) {
868 case 15: 886 case 15:
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 3b9416f4ee20..6a51448fd3f7 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -51,8 +51,6 @@ static inline unsigned int lx_get_pitch(unsigned int xres, int bpp)
51} 51}
52 52
53void lx_set_mode(struct fb_info *); 53void lx_set_mode(struct fb_info *);
54void lx_get_gamma(struct fb_info *, unsigned int *, int);
55void lx_set_gamma(struct fb_info *, unsigned int *, int);
56unsigned int lx_framebuffer_size(void); 54unsigned int lx_framebuffer_size(void);
57int lx_blank_display(struct fb_info *, int); 55int lx_blank_display(struct fb_info *, int);
58void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, 56void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
index aaef9165ec9b..b1cd49c99356 100644
--- a/drivers/video/geode/lxfb_ops.c
+++ b/drivers/video/geode/lxfb_ops.c
@@ -517,25 +517,25 @@ void lx_set_palette_reg(struct fb_info *info, unsigned regno,
517int lx_blank_display(struct fb_info *info, int blank_mode) 517int lx_blank_display(struct fb_info *info, int blank_mode)
518{ 518{
519 struct lxfb_par *par = info->par; 519 struct lxfb_par *par = info->par;
520 u32 dcfg, fp_pm; 520 u32 dcfg, misc, fp_pm;
521 int blank, hsync, vsync, crt; 521 int blank, hsync, vsync;
522 522
523 /* CRT power saving modes. */ 523 /* CRT power saving modes. */
524 switch (blank_mode) { 524 switch (blank_mode) {
525 case FB_BLANK_UNBLANK: 525 case FB_BLANK_UNBLANK:
526 blank = 0; hsync = 1; vsync = 1; crt = 1; 526 blank = 0; hsync = 1; vsync = 1;
527 break; 527 break;
528 case FB_BLANK_NORMAL: 528 case FB_BLANK_NORMAL:
529 blank = 1; hsync = 1; vsync = 1; crt = 1; 529 blank = 1; hsync = 1; vsync = 1;
530 break; 530 break;
531 case FB_BLANK_VSYNC_SUSPEND: 531 case FB_BLANK_VSYNC_SUSPEND:
532 blank = 1; hsync = 1; vsync = 0; crt = 1; 532 blank = 1; hsync = 1; vsync = 0;
533 break; 533 break;
534 case FB_BLANK_HSYNC_SUSPEND: 534 case FB_BLANK_HSYNC_SUSPEND:
535 blank = 1; hsync = 0; vsync = 1; crt = 1; 535 blank = 1; hsync = 0; vsync = 1;
536 break; 536 break;
537 case FB_BLANK_POWERDOWN: 537 case FB_BLANK_POWERDOWN:
538 blank = 1; hsync = 0; vsync = 0; crt = 0; 538 blank = 1; hsync = 0; vsync = 0;
539 break; 539 break;
540 default: 540 default:
541 return -EINVAL; 541 return -EINVAL;
@@ -545,15 +545,23 @@ int lx_blank_display(struct fb_info *info, int blank_mode)
545 dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN | 545 dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |
546 VP_DCFG_CRT_EN); 546 VP_DCFG_CRT_EN);
547 if (!blank) 547 if (!blank)
548 dcfg |= VP_DCFG_DAC_BL_EN; 548 dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;
549 if (hsync) 549 if (hsync)
550 dcfg |= VP_DCFG_HSYNC_EN; 550 dcfg |= VP_DCFG_HSYNC_EN;
551 if (vsync) 551 if (vsync)
552 dcfg |= VP_DCFG_VSYNC_EN; 552 dcfg |= VP_DCFG_VSYNC_EN;
553 if (crt) 553
554 dcfg |= VP_DCFG_CRT_EN;
555 write_vp(par, VP_DCFG, dcfg); 554 write_vp(par, VP_DCFG, dcfg);
556 555
556 misc = read_vp(par, VP_MISC);
557
558 if (vsync && hsync)
559 misc &= ~VP_MISC_DACPWRDN;
560 else
561 misc |= VP_MISC_DACPWRDN;
562
563 write_vp(par, VP_MISC, misc);
564
557 /* Power on/off flat panel */ 565 /* Power on/off flat panel */
558 566
559 if (par->output & OUTPUT_PANEL) { 567 if (par->output & OUTPUT_PANEL) {
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index c18880d9db1f..0129c044f6d6 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = {
551 * Initialization 551 * Initialization
552 */ 552 */
553 553
554static int __init hgafb_probe(struct device *device) 554static int __init hgafb_probe(struct platform_device *pdev)
555{ 555{
556 struct fb_info *info; 556 struct fb_info *info;
557 557
@@ -565,7 +565,7 @@ static int __init hgafb_probe(struct device *device)
565 printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n", 565 printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
566 hga_type_name, hga_vram_len/1024); 566 hga_type_name, hga_vram_len/1024);
567 567
568 info = framebuffer_alloc(0, NULL); 568 info = framebuffer_alloc(0, &pdev->dev);
569 if (!info) { 569 if (!info) {
570 iounmap(hga_vram); 570 iounmap(hga_vram);
571 return -ENOMEM; 571 return -ENOMEM;
@@ -593,13 +593,13 @@ static int __init hgafb_probe(struct device *device)
593 593
594 printk(KERN_INFO "fb%d: %s frame buffer device\n", 594 printk(KERN_INFO "fb%d: %s frame buffer device\n",
595 info->node, info->fix.id); 595 info->node, info->fix.id);
596 dev_set_drvdata(device, info); 596 platform_set_drvdata(pdev, info);
597 return 0; 597 return 0;
598} 598}
599 599
600static int hgafb_remove(struct device *device) 600static int hgafb_remove(struct platform_device *pdev)
601{ 601{
602 struct fb_info *info = dev_get_drvdata(device); 602 struct fb_info *info = platform_get_drvdata(pdev);
603 603
604 hga_txt_mode(); 604 hga_txt_mode();
605 hga_clear_screen(); 605 hga_clear_screen();
@@ -620,16 +620,15 @@ static int hgafb_remove(struct device *device)
620 return 0; 620 return 0;
621} 621}
622 622
623static struct device_driver hgafb_driver = { 623static struct platform_driver hgafb_driver = {
624 .name = "hgafb",
625 .bus = &platform_bus_type,
626 .probe = hgafb_probe, 624 .probe = hgafb_probe,
627 .remove = hgafb_remove, 625 .remove = hgafb_remove,
626 .driver = {
627 .name = "hgafb",
628 },
628}; 629};
629 630
630static struct platform_device hgafb_device = { 631static struct platform_device *hgafb_device;
631 .name = "hgafb",
632};
633 632
634static int __init hgafb_init(void) 633static int __init hgafb_init(void)
635{ 634{
@@ -638,12 +637,15 @@ static int __init hgafb_init(void)
638 if (fb_get_options("hgafb", NULL)) 637 if (fb_get_options("hgafb", NULL))
639 return -ENODEV; 638 return -ENODEV;
640 639
641 ret = driver_register(&hgafb_driver); 640 ret = platform_driver_register(&hgafb_driver);
642 641
643 if (!ret) { 642 if (!ret) {
644 ret = platform_device_register(&hgafb_device); 643 hgafb_device = platform_device_register_simple("hgafb", 0, NULL, 0);
645 if (ret) 644
646 driver_unregister(&hgafb_driver); 645 if (IS_ERR(hgafb_device)) {
646 platform_driver_unregister(&hgafb_driver);
647 ret = PTR_ERR(hgafb_device);
648 }
647 } 649 }
648 650
649 return ret; 651 return ret;
@@ -651,8 +653,8 @@ static int __init hgafb_init(void)
651 653
652static void __exit hgafb_exit(void) 654static void __exit hgafb_exit(void)
653{ 655{
654 platform_device_unregister(&hgafb_device); 656 platform_device_unregister(hgafb_device);
655 driver_unregister(&hgafb_driver); 657 platform_driver_unregister(&hgafb_driver);
656} 658}
657 659
658/* ------------------------------------------------------------------------- 660/* -------------------------------------------------------------------------
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 392a8be6aa76..e6467cf9f19f 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -27,7 +27,7 @@
27#include <asm/pgtable.h> 27#include <asm/pgtable.h>
28#include <asm/io.h> 28#include <asm/io.h>
29#include <asm/hd64461.h> 29#include <asm/hd64461.h>
30#include <asm/cpu/dac.h> 30#include <cpu/dac.h>
31 31
32#define WIDTH 640 32#define WIDTH 640
33 33
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
deleted file mode 100644
index 9366ef2bb5f7..000000000000
--- a/drivers/video/imacfb.c
+++ /dev/null
@@ -1,376 +0,0 @@
1/*
2 * framebuffer driver for Intel Based Mac's
3 *
4 * (c) 2006 Edgar Hucek <gimli@dark-green.com>
5 * Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
6 *
7 */
8
9#include <linux/delay.h>
10#include <linux/errno.h>
11#include <linux/fb.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/ioport.h>
15#include <linux/mm.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/screen_info.h>
19#include <linux/slab.h>
20#include <linux/string.h>
21#include <linux/dmi.h>
22#include <linux/efi.h>
23
24#include <asm/io.h>
25
26#include <video/vga.h>
27
28typedef enum _MAC_TYPE {
29 M_I17,
30 M_I20,
31 M_MINI,
32 M_MACBOOK,
33 M_UNKNOWN
34} MAC_TYPE;
35
36/* --------------------------------------------------------------------- */
37
38static struct fb_var_screeninfo imacfb_defined __initdata = {
39 .activate = FB_ACTIVATE_NOW,
40 .height = -1,
41 .width = -1,
42 .right_margin = 32,
43 .upper_margin = 16,
44 .lower_margin = 4,
45 .vsync_len = 4,
46 .vmode = FB_VMODE_NONINTERLACED,
47};
48
49static struct fb_fix_screeninfo imacfb_fix __initdata = {
50 .id = "IMAC VGA",
51 .type = FB_TYPE_PACKED_PIXELS,
52 .accel = FB_ACCEL_NONE,
53 .visual = FB_VISUAL_TRUECOLOR,
54};
55
56static int inverse;
57static int model = M_UNKNOWN;
58static int manual_height;
59static int manual_width;
60
61static int set_system(const struct dmi_system_id *id)
62{
63 printk(KERN_INFO "imacfb: %s detected - set system to %ld\n",
64 id->ident, (long)id->driver_data);
65
66 model = (long)id->driver_data;
67
68 return 0;
69}
70
71static struct dmi_system_id __initdata dmi_system_table[] = {
72 { set_system, "iMac4,1", {
73 DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
74 DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17},
75 { set_system, "MacBookPro1,1", {
76 DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
77 DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17},
78 { set_system, "MacBook1,1", {
79 DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
80 DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
81 { set_system, "Macmini1,1", {
82 DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
83 DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI},
84 {},
85};
86
87#define DEFAULT_FB_MEM 1024*1024*16
88
89/* --------------------------------------------------------------------- */
90
91static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green,
92 unsigned blue, unsigned transp,
93 struct fb_info *info)
94{
95 /*
96 * Set a single color register. The values supplied are
97 * already rounded down to the hardware's capabilities
98 * (according to the entries in the `var' structure). Return
99 * != 0 for invalid regno.
100 */
101
102 if (regno >= info->cmap.len)
103 return 1;
104
105 if (regno < 16) {
106 red >>= 8;
107 green >>= 8;
108 blue >>= 8;
109 ((u32 *)(info->pseudo_palette))[regno] =
110 (red << info->var.red.offset) |
111 (green << info->var.green.offset) |
112 (blue << info->var.blue.offset);
113 }
114 return 0;
115}
116
117static struct fb_ops imacfb_ops = {
118 .owner = THIS_MODULE,
119 .fb_setcolreg = imacfb_setcolreg,
120 .fb_fillrect = cfb_fillrect,
121 .fb_copyarea = cfb_copyarea,
122 .fb_imageblit = cfb_imageblit,
123};
124
125static int __init imacfb_setup(char *options)
126{
127 char *this_opt;
128
129 if (!options || !*options)
130 return 0;
131
132 while ((this_opt = strsep(&options, ",")) != NULL) {
133 if (!*this_opt) continue;
134
135 if (!strcmp(this_opt, "inverse"))
136 inverse = 1;
137 else if (!strcmp(this_opt, "i17"))
138 model = M_I17;
139 else if (!strcmp(this_opt, "i20"))
140 model = M_I20;
141 else if (!strcmp(this_opt, "mini"))
142 model = M_MINI;
143 else if (!strcmp(this_opt, "macbook"))
144 model = M_MACBOOK;
145 else if (!strncmp(this_opt, "height:", 7))
146 manual_height = simple_strtoul(this_opt+7, NULL, 0);
147 else if (!strncmp(this_opt, "width:", 6))
148 manual_width = simple_strtoul(this_opt+6, NULL, 0);
149 }
150 return 0;
151}
152
153static int __init imacfb_probe(struct platform_device *dev)
154{
155 struct fb_info *info;
156 int err;
157 unsigned int size_vmode;
158 unsigned int size_remap;
159 unsigned int size_total;
160
161 screen_info.lfb_depth = 32;
162 screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000;
163 screen_info.pages=1;
164 screen_info.blue_size = 8;
165 screen_info.blue_pos = 0;
166 screen_info.green_size = 8;
167 screen_info.green_pos = 8;
168 screen_info.red_size = 8;
169 screen_info.red_pos = 16;
170 screen_info.rsvd_size = 8;
171 screen_info.rsvd_pos = 24;
172
173 switch (model) {
174 case M_I17:
175 screen_info.lfb_width = 1440;
176 screen_info.lfb_height = 900;
177 screen_info.lfb_linelength = 1472 * 4;
178 screen_info.lfb_base = 0x80010000;
179 break;
180 case M_I20:
181 screen_info.lfb_width = 1680;
182 screen_info.lfb_height = 1050;
183 screen_info.lfb_linelength = 1728 * 4;
184 screen_info.lfb_base = 0x80010000;
185 break;
186 case M_MINI:
187 screen_info.lfb_width = 1024;
188 screen_info.lfb_height = 768;
189 screen_info.lfb_linelength = 2048 * 4;
190 screen_info.lfb_base = 0x80000000;
191 break;
192 case M_MACBOOK:
193 screen_info.lfb_width = 1280;
194 screen_info.lfb_height = 800;
195 screen_info.lfb_linelength = 2048 * 4;
196 screen_info.lfb_base = 0x80000000;
197 break;
198 }
199
200 /* if the user wants to manually specify height/width,
201 we will override the defaults */
202 /* TODO: eventually get auto-detection working */
203 if (manual_height > 0)
204 screen_info.lfb_height = manual_height;
205 if (manual_width > 0)
206 screen_info.lfb_width = manual_width;
207
208 imacfb_fix.smem_start = screen_info.lfb_base;
209 imacfb_defined.bits_per_pixel = screen_info.lfb_depth;
210 imacfb_defined.xres = screen_info.lfb_width;
211 imacfb_defined.yres = screen_info.lfb_height;
212 imacfb_fix.line_length = screen_info.lfb_linelength;
213
214 /* size_vmode -- that is the amount of memory needed for the
215 * used video mode, i.e. the minimum amount of
216 * memory we need. */
217 size_vmode = imacfb_defined.yres * imacfb_fix.line_length;
218
219 /* size_total -- all video memory we have. Used for
220 * entries, ressource allocation and bounds
221 * checking. */
222 size_total = screen_info.lfb_size * 65536;
223 if (size_total < size_vmode)
224 size_total = size_vmode;
225
226 /* size_remap -- the amount of video memory we are going to
227 * use for imacfb. With modern cards it is no
228 * option to simply use size_total as that
229 * wastes plenty of kernel address space. */
230 size_remap = size_vmode * 2;
231 if (size_remap < size_vmode)
232 size_remap = size_vmode;
233 if (size_remap > size_total)
234 size_remap = size_total;
235 imacfb_fix.smem_len = size_remap;
236
237 if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
238 printk(KERN_WARNING
239 "imacfb: cannot reserve video memory at 0x%lx\n",
240 imacfb_fix.smem_start);
241 /* We cannot make this fatal. Sometimes this comes from magic
242 spaces our resource handlers simply don't know about */
243 }
244
245 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
246 if (!info) {
247 err = -ENOMEM;
248 goto err_release_mem;
249 }
250 info->pseudo_palette = info->par;
251 info->par = NULL;
252
253 info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len);
254 if (!info->screen_base) {
255 printk(KERN_ERR "imacfb: abort, cannot ioremap video memory "
256 "0x%x @ 0x%lx\n",
257 imacfb_fix.smem_len, imacfb_fix.smem_start);
258 err = -EIO;
259 goto err_unmap;
260 }
261
262 printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, "
263 "using %dk, total %dk\n",
264 imacfb_fix.smem_start, info->screen_base,
265 size_remap/1024, size_total/1024);
266 printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
267 imacfb_defined.xres, imacfb_defined.yres,
268 imacfb_defined.bits_per_pixel, imacfb_fix.line_length,
269 screen_info.pages);
270
271 imacfb_defined.xres_virtual = imacfb_defined.xres;
272 imacfb_defined.yres_virtual = imacfb_fix.smem_len /
273 imacfb_fix.line_length;
274 printk(KERN_INFO "imacfb: scrolling: redraw\n");
275 imacfb_defined.yres_virtual = imacfb_defined.yres;
276
277 /* some dummy values for timing to make fbset happy */
278 imacfb_defined.pixclock = 10000000 / imacfb_defined.xres *
279 1000 / imacfb_defined.yres;
280 imacfb_defined.left_margin = (imacfb_defined.xres / 8) & 0xf8;
281 imacfb_defined.hsync_len = (imacfb_defined.xres / 8) & 0xf8;
282
283 imacfb_defined.red.offset = screen_info.red_pos;
284 imacfb_defined.red.length = screen_info.red_size;
285 imacfb_defined.green.offset = screen_info.green_pos;
286 imacfb_defined.green.length = screen_info.green_size;
287 imacfb_defined.blue.offset = screen_info.blue_pos;
288 imacfb_defined.blue.length = screen_info.blue_size;
289 imacfb_defined.transp.offset = screen_info.rsvd_pos;
290 imacfb_defined.transp.length = screen_info.rsvd_size;
291
292 printk(KERN_INFO "imacfb: %s: "
293 "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
294 "Truecolor",
295 screen_info.rsvd_size,
296 screen_info.red_size,
297 screen_info.green_size,
298 screen_info.blue_size,
299 screen_info.rsvd_pos,
300 screen_info.red_pos,
301 screen_info.green_pos,
302 screen_info.blue_pos);
303
304 imacfb_fix.ypanstep = 0;
305 imacfb_fix.ywrapstep = 0;
306
307 /* request failure does not faze us, as vgacon probably has this
308 * region already (FIXME) */
309 request_region(0x3c0, 32, "imacfb");
310
311 info->fbops = &imacfb_ops;
312 info->var = imacfb_defined;
313 info->fix = imacfb_fix;
314 info->flags = FBINFO_FLAG_DEFAULT;
315
316 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
317 err = -ENOMEM;
318 goto err_unmap;
319 }
320 if (register_framebuffer(info)<0) {
321 err = -EINVAL;
322 goto err_fb_dealoc;
323 }
324 printk(KERN_INFO "fb%d: %s frame buffer device\n",
325 info->node, info->fix.id);
326 return 0;
327
328err_fb_dealoc:
329 fb_dealloc_cmap(&info->cmap);
330err_unmap:
331 iounmap(info->screen_base);
332 framebuffer_release(info);
333err_release_mem:
334 release_mem_region(imacfb_fix.smem_start, size_total);
335 return err;
336}
337
338static struct platform_driver imacfb_driver = {
339 .probe = imacfb_probe,
340 .driver = {
341 .name = "imacfb",
342 },
343};
344
345static struct platform_device imacfb_device = {
346 .name = "imacfb",
347};
348
349static int __init imacfb_init(void)
350{
351 int ret;
352 char *option = NULL;
353
354 if (!efi_enabled)
355 return -ENODEV;
356 if (!dmi_check_system(dmi_system_table))
357 return -ENODEV;
358 if (model == M_UNKNOWN)
359 return -ENODEV;
360
361 if (fb_get_options("imacfb", &option))
362 return -ENODEV;
363
364 imacfb_setup(option);
365 ret = platform_driver_register(&imacfb_driver);
366
367 if (!ret) {
368 ret = platform_device_register(&imacfb_device);
369 if (ret)
370 platform_driver_unregister(&imacfb_driver);
371 }
372 return ret;
373}
374module_init(imacfb_init);
375
376MODULE_LICENSE("GPL");
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 94e4d3ac1a05..ccd986140c95 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -24,6 +24,7 @@
24#include <linux/string.h> 24#include <linux/string.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/mm.h>
27#include <linux/fb.h> 28#include <linux/fb.h>
28#include <linux/delay.h> 29#include <linux/delay.h>
29#include <linux/init.h> 30#include <linux/init.h>
@@ -32,9 +33,9 @@
32#include <linux/platform_device.h> 33#include <linux/platform_device.h>
33#include <linux/dma-mapping.h> 34#include <linux/dma-mapping.h>
34 35
35#include <asm/hardware.h> 36#include <mach/hardware.h>
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/arch/imxfb.h> 38#include <mach/imxfb.h>
38 39
39/* 40/*
40 * Complain if VAR is out of range. 41 * Complain if VAR is out of range.
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 3325fbd68ab3..a50bea614804 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -12,9 +12,9 @@
12#endif 12#endif
13 13
14/*** Version/name ***/ 14/*** Version/name ***/
15#define INTELFB_VERSION "0.9.5" 15#define INTELFB_VERSION "0.9.6"
16#define INTELFB_MODULE_NAME "intelfb" 16#define INTELFB_MODULE_NAME "intelfb"
17#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM" 17#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
18 18
19 19
20/*** Debug/feature defines ***/ 20/*** Debug/feature defines ***/
@@ -58,6 +58,7 @@
58#define PCI_DEVICE_ID_INTEL_915GM 0x2592 58#define PCI_DEVICE_ID_INTEL_915GM 0x2592
59#define PCI_DEVICE_ID_INTEL_945G 0x2772 59#define PCI_DEVICE_ID_INTEL_945G 0x2772
60#define PCI_DEVICE_ID_INTEL_945GM 0x27A2 60#define PCI_DEVICE_ID_INTEL_945GM 0x27A2
61#define PCI_DEVICE_ID_INTEL_945GME 0x27AE
61#define PCI_DEVICE_ID_INTEL_965G 0x29A2 62#define PCI_DEVICE_ID_INTEL_965G 0x29A2
62#define PCI_DEVICE_ID_INTEL_965GM 0x2A02 63#define PCI_DEVICE_ID_INTEL_965GM 0x2A02
63 64
@@ -160,6 +161,7 @@ enum intel_chips {
160 INTEL_915GM, 161 INTEL_915GM,
161 INTEL_945G, 162 INTEL_945G,
162 INTEL_945GM, 163 INTEL_945GM,
164 INTEL_945GME,
163 INTEL_965G, 165 INTEL_965G,
164 INTEL_965GM, 166 INTEL_965GM,
165}; 167};
@@ -363,6 +365,7 @@ struct intelfb_info {
363 ((dinfo)->chipset == INTEL_915GM) || \ 365 ((dinfo)->chipset == INTEL_915GM) || \
364 ((dinfo)->chipset == INTEL_945G) || \ 366 ((dinfo)->chipset == INTEL_945G) || \
365 ((dinfo)->chipset == INTEL_945GM) || \ 367 ((dinfo)->chipset == INTEL_945GM) || \
368 ((dinfo)->chipset == INTEL_945GME) || \
366 ((dinfo)->chipset == INTEL_965G) || \ 369 ((dinfo)->chipset == INTEL_965G) || \
367 ((dinfo)->chipset == INTEL_965GM)) 370 ((dinfo)->chipset == INTEL_965GM))
368 371
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c
index fcf9fadbf572..5d896b81f4e0 100644
--- a/drivers/video/intelfb/intelfb_i2c.c
+++ b/drivers/video/intelfb/intelfb_i2c.c
@@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
171 /* has some LVDS + tv-out */ 171 /* has some LVDS + tv-out */
172 case INTEL_945G: 172 case INTEL_945G:
173 case INTEL_945GM: 173 case INTEL_945GM:
174 case INTEL_945GME:
174 case INTEL_965G: 175 case INTEL_965G:
175 case INTEL_965GM: 176 case INTEL_965GM:
176 /* SDVO ports have a single control bus - 2 devices */ 177 /* SDVO ports have a single control bus - 2 devices */
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index e44303f9bc52..a09e23649357 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -2,7 +2,7 @@
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 * 945G/945GM/965G/965GM integrated graphics chips. 5 * 945G/945GM/945GME/965G/965GM 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
@@ -102,6 +102,9 @@
102 * 102 *
103 * 04/2008 - Version 0.9.5 103 * 04/2008 - Version 0.9.5
104 * Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>) 104 * Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
105 *
106 * 08/2008 - Version 0.9.6
107 * Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
105 */ 108 */
106 109
107#include <linux/module.h> 110#include <linux/module.h>
@@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
183 { 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 },
184 { 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 }, 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 },
185 { 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 }, 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 },
189 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
186 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G }, 190 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
187 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM }, 191 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
188 { 0, } 192 { 0, }
@@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
555 (ent->device == PCI_DEVICE_ID_INTEL_915GM) || 559 (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
556 (ent->device == PCI_DEVICE_ID_INTEL_945G) || 560 (ent->device == PCI_DEVICE_ID_INTEL_945G) ||
557 (ent->device == PCI_DEVICE_ID_INTEL_945GM) || 561 (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
562 (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
558 (ent->device == PCI_DEVICE_ID_INTEL_965G) || 563 (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
559 (ent->device == PCI_DEVICE_ID_INTEL_965GM)) { 564 (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
560 565
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 8e6d6a4db0ad..8b26b27c2db6 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
143 dinfo->mobile = 1; 143 dinfo->mobile = 1;
144 dinfo->pll_index = PLLS_I9xx; 144 dinfo->pll_index = PLLS_I9xx;
145 return 0; 145 return 0;
146 case PCI_DEVICE_ID_INTEL_945GME:
147 dinfo->name = "Intel(R) 945GME";
148 dinfo->chipset = INTEL_945GME;
149 dinfo->mobile = 1;
150 dinfo->pll_index = PLLS_I9xx;
151 return 0;
146 case PCI_DEVICE_ID_INTEL_965G: 152 case PCI_DEVICE_ID_INTEL_965G:
147 dinfo->name = "Intel(R) 965G"; 153 dinfo->name = "Intel(R) 965G";
148 dinfo->chipset = INTEL_965G; 154 dinfo->chipset = INTEL_965G;
@@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
186 case PCI_DEVICE_ID_INTEL_915GM: 192 case PCI_DEVICE_ID_INTEL_915GM:
187 case PCI_DEVICE_ID_INTEL_945G: 193 case PCI_DEVICE_ID_INTEL_945G:
188 case PCI_DEVICE_ID_INTEL_945GM: 194 case PCI_DEVICE_ID_INTEL_945GM:
195 case PCI_DEVICE_ID_INTEL_945GME:
189 case PCI_DEVICE_ID_INTEL_965G: 196 case PCI_DEVICE_ID_INTEL_965G:
190 case PCI_DEVICE_ID_INTEL_965GM: 197 case PCI_DEVICE_ID_INTEL_965GM:
191 /* 915, 945 and 965 chipsets support a 256MB aperture. 198 /* 915, 945 and 965 chipsets support a 256MB aperture.
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 13fea61d6ae4..7c7e8c2da9d9 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -33,6 +33,7 @@ static int leo_blank(int, struct fb_info *);
33 33
34static int leo_mmap(struct fb_info *, struct vm_area_struct *); 34static int leo_mmap(struct fb_info *, struct vm_area_struct *);
35static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); 35static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
36static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
36 37
37/* 38/*
38 * Frame buffer operations 39 * Frame buffer operations
@@ -42,6 +43,7 @@ static struct fb_ops leo_ops = {
42 .owner = THIS_MODULE, 43 .owner = THIS_MODULE,
43 .fb_setcolreg = leo_setcolreg, 44 .fb_setcolreg = leo_setcolreg,
44 .fb_blank = leo_blank, 45 .fb_blank = leo_blank,
46 .fb_pan_display = leo_pan_display,
45 .fb_fillrect = cfb_fillrect, 47 .fb_fillrect = cfb_fillrect,
46 .fb_copyarea = cfb_copyarea, 48 .fb_copyarea = cfb_copyarea,
47 .fb_imageblit = cfb_imageblit, 49 .fb_imageblit = cfb_imageblit,
@@ -206,6 +208,60 @@ static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
206 return; 208 return;
207} 209}
208 210
211static void leo_switch_from_graph(struct fb_info *info)
212{
213 struct leo_par *par = (struct leo_par *) info->par;
214 struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
215 struct leo_cursor __iomem *cursor = par->cursor;
216 unsigned long flags;
217 u32 val;
218
219 spin_lock_irqsave(&par->lock, flags);
220
221 par->extent = ((info->var.xres - 1) |
222 ((info->var.yres - 1) << 16));
223
224 sbus_writel(0xffffffff, &ss->wid);
225 sbus_writel(0xffff, &ss->wmask);
226 sbus_writel(0, &ss->vclipmin);
227 sbus_writel(par->extent, &ss->vclipmax);
228 sbus_writel(0, &ss->fg);
229 sbus_writel(0xff000000, &ss->planemask);
230 sbus_writel(0x310850, &ss->rop);
231 sbus_writel(0, &ss->widclip);
232 sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
233 &par->lc_ss0_usr->extent);
234 sbus_writel(4, &par->lc_ss0_usr->addrspace);
235 sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
236 sbus_writel(0, &par->lc_ss0_usr->fontt);
237 do {
238 val = sbus_readl(&par->lc_ss0_usr->csr);
239 } while (val & 0x20000000);
240
241 /* setup screen buffer for cfb_* functions */
242 sbus_writel(1, &ss->wid);
243 sbus_writel(0x00ffffff, &ss->planemask);
244 sbus_writel(0x310b90, &ss->rop);
245 sbus_writel(0, &par->lc_ss0_usr->addrspace);
246
247 /* hide cursor */
248 sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc);
249
250 spin_unlock_irqrestore(&par->lock, flags);
251}
252
253static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
254{
255 /* We just use this to catch switches out of
256 * graphics mode.
257 */
258 leo_switch_from_graph(info);
259
260 if (var->xoffset || var->yoffset || var->vmode)
261 return -EINVAL;
262 return 0;
263}
264
209/** 265/**
210 * leo_setcolreg - Optional function. Sets a color register. 266 * leo_setcolreg - Optional function. Sets a color register.
211 * @regno: boolean, 0 copy local, 1 get_user() function 267 * @regno: boolean, 0 copy local, 1 get_user() function
@@ -454,44 +510,6 @@ static void leo_init_wids(struct fb_info *info)
454 leo_wid_put(info, &wl); 510 leo_wid_put(info, &wl);
455} 511}
456 512
457static void leo_switch_from_graph(struct fb_info *info)
458{
459 struct leo_par *par = (struct leo_par *) info->par;
460 struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
461 unsigned long flags;
462 u32 val;
463
464 spin_lock_irqsave(&par->lock, flags);
465
466 par->extent = ((info->var.xres - 1) |
467 ((info->var.yres - 1) << 16));
468
469 sbus_writel(0xffffffff, &ss->wid);
470 sbus_writel(0xffff, &ss->wmask);
471 sbus_writel(0, &ss->vclipmin);
472 sbus_writel(par->extent, &ss->vclipmax);
473 sbus_writel(0, &ss->fg);
474 sbus_writel(0xff000000, &ss->planemask);
475 sbus_writel(0x310850, &ss->rop);
476 sbus_writel(0, &ss->widclip);
477 sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
478 &par->lc_ss0_usr->extent);
479 sbus_writel(4, &par->lc_ss0_usr->addrspace);
480 sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
481 sbus_writel(0, &par->lc_ss0_usr->fontt);
482 do {
483 val = sbus_readl(&par->lc_ss0_usr->csr);
484 } while (val & 0x20000000);
485
486 /* setup screen buffer for cfb_* functions */
487 sbus_writel(1, &ss->wid);
488 sbus_writel(0x00ffffff, &ss->planemask);
489 sbus_writel(0x310b90, &ss->rop);
490 sbus_writel(0, &par->lc_ss0_usr->addrspace);
491
492 spin_unlock_irqrestore(&par->lock, flags);
493}
494
495static void leo_init_hw(struct fb_info *info) 513static void leo_init_hw(struct fb_info *info)
496{ 514{
497 struct leo_par *par = (struct leo_par *) info->par; 515 struct leo_par *par = (struct leo_par *) info->par;
@@ -641,7 +659,7 @@ static int __devexit leo_remove(struct of_device *op)
641 return 0; 659 return 0;
642} 660}
643 661
644static struct of_device_id leo_match[] = { 662static const struct of_device_id leo_match[] = {
645 { 663 {
646 .name = "SUNW,leo", 664 .name = "SUNW,leo",
647 }, 665 },
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index aa8c714d6245..b790ddff76f9 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -596,7 +596,7 @@ static struct fb_ops macfb_ops = {
596 .fb_imageblit = cfb_imageblit, 596 .fb_imageblit = cfb_imageblit,
597}; 597};
598 598
599void __init macfb_setup(char *options) 599static void __init macfb_setup(char *options)
600{ 600{
601 char *this_opt; 601 char *this_opt;
602 602
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 75ee5a12e549..c14e3e2212b3 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -87,13 +87,7 @@ static int matroxfb_gpio_getscl(void* data) {
87 return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0; 87 return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
88} 88}
89 89
90static struct i2c_adapter matrox_i2c_adapter_template = 90static const struct i2c_algo_bit_data matrox_i2c_algo_template =
91{
92 .owner = THIS_MODULE,
93 .id = I2C_HW_B_G400,
94};
95
96static struct i2c_algo_bit_data matrox_i2c_algo_template =
97{ 91{
98 .setsda = matroxfb_gpio_setsda, 92 .setsda = matroxfb_gpio_setsda,
99 .setscl = matroxfb_gpio_setscl, 93 .setscl = matroxfb_gpio_setscl,
@@ -112,7 +106,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
112 b->minfo = minfo; 106 b->minfo = minfo;
113 b->mask.data = data; 107 b->mask.data = data;
114 b->mask.clock = clock; 108 b->mask.clock = clock;
115 b->adapter = matrox_i2c_adapter_template; 109 b->adapter.owner = THIS_MODULE;
116 snprintf(b->adapter.name, sizeof(b->adapter.name), name, 110 snprintf(b->adapter.name, sizeof(b->adapter.name), name,
117 minfo->fbcon.node); 111 minfo->fbcon.node);
118 i2c_set_adapdata(&b->adapter, b); 112 i2c_set_adapdata(&b->adapter, b);
@@ -187,6 +181,17 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
187 MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0); 181 MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
188 if (err) 182 if (err)
189 printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); 183 printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
184 else {
185 struct i2c_board_info maven_info = {
186 I2C_BOARD_INFO("maven", 0x1b),
187 };
188 unsigned short const addr_list[2] = {
189 0x1b, I2C_CLIENT_END
190 };
191
192 i2c_new_probed_device(&m2info->maven.adapter,
193 &maven_info, addr_list);
194 }
190 } 195 }
191 return m2info; 196 return m2info;
192fail_ddc1:; 197fail_ddc1:;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 54e82f35353d..8e7a275df50c 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1453,6 +1453,13 @@ static struct board {
1453 MGA_G100, 1453 MGA_G100,
1454 &vbG100, 1454 &vbG100,
1455 "MGA-G100 (AGP)"}, 1455 "MGA-G100 (AGP)"},
1456 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI, 0xFF,
1457 0, 0,
1458 DEVF_G200,
1459 230000,
1460 MGA_G200,
1461 &vbG200,
1462 "MGA-G200eV (PCI)"},
1456 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF, 1463 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
1457 0, 0, 1464 0, 0,
1458 DEVF_G200, 1465 DEVF_G200,
@@ -2118,6 +2125,8 @@ static struct pci_device_id matroxfb_devices[] = {
2118 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2125 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2119 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 2126 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
2120 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2127 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2128 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI,
2129 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2121 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 2130 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
2122 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 2131 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2123 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 2132 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
@@ -2536,7 +2545,7 @@ module_param(fh, int, 0);
2536MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz"); 2545MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
2537module_param(fv, int, 0); 2546module_param(fv, int, 0);
2538MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n" 2547MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
2539"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n"); 2548"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"");
2540module_param(grayscale, int, 0); 2549module_param(grayscale, int, 0);
2541MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)"); 2550MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
2542module_param(cross4MB, int, 0); 2551module_param(cross4MB, int, 0);
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 89da27bd5c49..042408a8c631 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -19,8 +19,6 @@
19#include <linux/matroxfb.h> 19#include <linux/matroxfb.h>
20#include <asm/div64.h> 20#include <asm/div64.h>
21 21
22#define MAVEN_I2CID (0x1B)
23
24#define MGATVO_B 1 22#define MGATVO_B 1
25#define MGATVO_C 2 23#define MGATVO_C 2
26 24
@@ -128,7 +126,7 @@ static int get_ctrl_id(__u32 v4l2_id) {
128 126
129struct maven_data { 127struct maven_data {
130 struct matrox_fb_info* primary_head; 128 struct matrox_fb_info* primary_head;
131 struct i2c_client client; 129 struct i2c_client *client;
132 int version; 130 int version;
133}; 131};
134 132
@@ -974,7 +972,7 @@ static inline int maven_compute_timming(struct maven_data* md,
974 972
975static int maven_program_timming(struct maven_data* md, 973static int maven_program_timming(struct maven_data* md,
976 const struct mavenregs* m) { 974 const struct mavenregs* m) {
977 struct i2c_client* c = &md->client; 975 struct i2c_client *c = md->client;
978 976
979 if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { 977 if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
980 LR(0x80); 978 LR(0x80);
@@ -1011,7 +1009,7 @@ static int maven_program_timming(struct maven_data* md,
1011} 1009}
1012 1010
1013static inline int maven_resync(struct maven_data* md) { 1011static inline int maven_resync(struct maven_data* md) {
1014 struct i2c_client* c = &md->client; 1012 struct i2c_client *c = md->client;
1015 maven_set_reg(c, 0x95, 0x20); /* start whole thing */ 1013 maven_set_reg(c, 0x95, 0x20); /* start whole thing */
1016 return 0; 1014 return 0;
1017} 1015}
@@ -1069,48 +1067,48 @@ static int maven_set_control (struct maven_data* md,
1069 maven_compute_bwlevel(md, &blacklevel, &whitelevel); 1067 maven_compute_bwlevel(md, &blacklevel, &whitelevel);
1070 blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); 1068 blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
1071 whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); 1069 whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
1072 maven_set_reg_pair(&md->client, 0x0e, blacklevel); 1070 maven_set_reg_pair(md->client, 0x0e, blacklevel);
1073 maven_set_reg_pair(&md->client, 0x1e, whitelevel); 1071 maven_set_reg_pair(md->client, 0x1e, whitelevel);
1074 } 1072 }
1075 break; 1073 break;
1076 case V4L2_CID_SATURATION: 1074 case V4L2_CID_SATURATION:
1077 { 1075 {
1078 maven_set_reg(&md->client, 0x20, p->value); 1076 maven_set_reg(md->client, 0x20, p->value);
1079 maven_set_reg(&md->client, 0x22, p->value); 1077 maven_set_reg(md->client, 0x22, p->value);
1080 } 1078 }
1081 break; 1079 break;
1082 case V4L2_CID_HUE: 1080 case V4L2_CID_HUE:
1083 { 1081 {
1084 maven_set_reg(&md->client, 0x25, p->value); 1082 maven_set_reg(md->client, 0x25, p->value);
1085 } 1083 }
1086 break; 1084 break;
1087 case V4L2_CID_GAMMA: 1085 case V4L2_CID_GAMMA:
1088 { 1086 {
1089 const struct maven_gamma* g; 1087 const struct maven_gamma* g;
1090 g = maven_compute_gamma(md); 1088 g = maven_compute_gamma(md);
1091 maven_set_reg(&md->client, 0x83, g->reg83); 1089 maven_set_reg(md->client, 0x83, g->reg83);
1092 maven_set_reg(&md->client, 0x84, g->reg84); 1090 maven_set_reg(md->client, 0x84, g->reg84);
1093 maven_set_reg(&md->client, 0x85, g->reg85); 1091 maven_set_reg(md->client, 0x85, g->reg85);
1094 maven_set_reg(&md->client, 0x86, g->reg86); 1092 maven_set_reg(md->client, 0x86, g->reg86);
1095 maven_set_reg(&md->client, 0x87, g->reg87); 1093 maven_set_reg(md->client, 0x87, g->reg87);
1096 maven_set_reg(&md->client, 0x88, g->reg88); 1094 maven_set_reg(md->client, 0x88, g->reg88);
1097 maven_set_reg(&md->client, 0x89, g->reg89); 1095 maven_set_reg(md->client, 0x89, g->reg89);
1098 maven_set_reg(&md->client, 0x8a, g->reg8a); 1096 maven_set_reg(md->client, 0x8a, g->reg8a);
1099 maven_set_reg(&md->client, 0x8b, g->reg8b); 1097 maven_set_reg(md->client, 0x8b, g->reg8b);
1100 } 1098 }
1101 break; 1099 break;
1102 case MATROXFB_CID_TESTOUT: 1100 case MATROXFB_CID_TESTOUT:
1103 { 1101 {
1104 unsigned char val 1102 unsigned char val
1105 = maven_get_reg(&md->client,0x8d); 1103 = maven_get_reg(md->client, 0x8d);
1106 if (p->value) val |= 0x10; 1104 if (p->value) val |= 0x10;
1107 else val &= ~0x10; 1105 else val &= ~0x10;
1108 maven_set_reg(&md->client, 0x8d, val); 1106 maven_set_reg(md->client, 0x8d, val);
1109 } 1107 }
1110 break; 1108 break;
1111 case MATROXFB_CID_DEFLICKER: 1109 case MATROXFB_CID_DEFLICKER:
1112 { 1110 {
1113 maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); 1111 maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
1114 } 1112 }
1115 break; 1113 break;
1116 } 1114 }
@@ -1189,6 +1187,7 @@ static int maven_init_client(struct i2c_client* clnt) {
1189 MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); 1187 MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo);
1190 1188
1191 md->primary_head = MINFO; 1189 md->primary_head = MINFO;
1190 md->client = clnt;
1192 down_write(&ACCESS_FBINFO(altout.lock)); 1191 down_write(&ACCESS_FBINFO(altout.lock));
1193 ACCESS_FBINFO(outputs[1]).output = &maven_altout; 1192 ACCESS_FBINFO(outputs[1]).output = &maven_altout;
1194 ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; 1193 ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src;
@@ -1232,14 +1231,11 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
1232 return 0; 1231 return 0;
1233} 1232}
1234 1233
1235static const unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END }; 1234static int maven_probe(struct i2c_client *client,
1236I2C_CLIENT_INSMOD; 1235 const struct i2c_device_id *id)
1237 1236{
1238static struct i2c_driver maven_driver; 1237 struct i2c_adapter *adapter = client->adapter;
1239 1238 int err = -ENODEV;
1240static int maven_detect_client(struct i2c_adapter* adapter, int address, int kind) {
1241 int err = 0;
1242 struct i2c_client* new_client;
1243 struct maven_data* data; 1239 struct maven_data* data;
1244 1240
1245 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA | 1241 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
@@ -1250,50 +1246,37 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin
1250 err = -ENOMEM; 1246 err = -ENOMEM;
1251 goto ERROR0; 1247 goto ERROR0;
1252 } 1248 }
1253 new_client = &data->client; 1249 i2c_set_clientdata(client, data);
1254 i2c_set_clientdata(new_client, data); 1250 err = maven_init_client(client);
1255 new_client->addr = address;
1256 new_client->adapter = adapter;
1257 new_client->driver = &maven_driver;
1258 new_client->flags = 0;
1259 strlcpy(new_client->name, "maven", I2C_NAME_SIZE);
1260 if ((err = i2c_attach_client(new_client)))
1261 goto ERROR3;
1262 err = maven_init_client(new_client);
1263 if (err) 1251 if (err)
1264 goto ERROR4; 1252 goto ERROR4;
1265 return 0; 1253 return 0;
1266ERROR4:; 1254ERROR4:;
1267 i2c_detach_client(new_client); 1255 kfree(data);
1268ERROR3:;
1269 kfree(new_client);
1270ERROR0:; 1256ERROR0:;
1271 return err; 1257 return err;
1272} 1258}
1273 1259
1274static int maven_attach_adapter(struct i2c_adapter* adapter) { 1260static int maven_remove(struct i2c_client *client)
1275 if (adapter->id == I2C_HW_B_G400) 1261{
1276 return i2c_probe(adapter, &addr_data, &maven_detect_client);
1277 return 0;
1278}
1279
1280static int maven_detach_client(struct i2c_client* client) {
1281 int err;
1282
1283 if ((err = i2c_detach_client(client)))
1284 return err;
1285 maven_shutdown_client(client); 1262 maven_shutdown_client(client);
1286 kfree(i2c_get_clientdata(client)); 1263 kfree(i2c_get_clientdata(client));
1287 return 0; 1264 return 0;
1288} 1265}
1289 1266
1267static const struct i2c_device_id maven_id[] = {
1268 { "maven", 0 },
1269 { }
1270};
1271MODULE_DEVICE_TABLE(i2c, maven_id);
1272
1290static struct i2c_driver maven_driver={ 1273static struct i2c_driver maven_driver={
1291 .driver = { 1274 .driver = {
1292 .name = "maven", 1275 .name = "maven",
1293 }, 1276 },
1294 .id = I2C_DRIVERID_MGATVO, 1277 .probe = maven_probe,
1295 .attach_adapter = maven_attach_adapter, 1278 .remove = maven_remove,
1296 .detach_client = maven_detach_client, 1279 .id_table = maven_id,
1297}; 1280};
1298 1281
1299static int __init matroxfb_maven_init(void) 1282static int __init matroxfb_maven_init(void)
diff --git a/drivers/video/metronomefb.c b/drivers/video/metronomefb.c
index cc4c038a1b3f..df1f757a6161 100644
--- a/drivers/video/metronomefb.c
+++ b/drivers/video/metronomefb.c
@@ -40,29 +40,63 @@
40 40
41#include <asm/unaligned.h> 41#include <asm/unaligned.h>
42 42
43
44#define DEBUG 1
45#ifdef DEBUG
46#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
47#else
48#define DPRINTK(f, a...)
49#endif
50
51
52/* Display specific information */ 43/* Display specific information */
53#define DPY_W 832 44#define DPY_W 832
54#define DPY_H 622 45#define DPY_H 622
55 46
47static int user_wfm_size;
48
56/* frame differs from image. frame includes non-visible pixels */ 49/* frame differs from image. frame includes non-visible pixels */
57struct epd_frame { 50struct epd_frame {
58 int fw; /* frame width */ 51 int fw; /* frame width */
59 int fh; /* frame height */ 52 int fh; /* frame height */
53 u16 config[4];
54 int wfm_size;
60}; 55};
61 56
62static struct epd_frame epd_frame_table[] = { 57static struct epd_frame epd_frame_table[] = {
63 { 58 {
64 .fw = 832, 59 .fw = 832,
65 .fh = 622 60 .fh = 622,
61 .config = {
62 15 /* sdlew */
63 | 2 << 8 /* sdosz */
64 | 0 << 11 /* sdor */
65 | 0 << 12 /* sdces */
66 | 0 << 15, /* sdcer */
67 42 /* gdspl */
68 | 1 << 8 /* gdr1 */
69 | 1 << 9 /* sdshr */
70 | 0 << 15, /* gdspp */
71 18 /* gdspw */
72 | 0 << 15, /* dispc */
73 599 /* vdlc */
74 | 0 << 11 /* dsi */
75 | 0 << 12, /* dsic */
76 },
77 .wfm_size = 47001,
78 },
79 {
80 .fw = 1088,
81 .fh = 791,
82 .config = {
83 0x0104,
84 0x031f,
85 0x0088,
86 0x02ff,
87 },
88 .wfm_size = 46770,
89 },
90 {
91 .fw = 1200,
92 .fh = 842,
93 .config = {
94 0x0101,
95 0x030e,
96 0x0012,
97 0x0280,
98 },
99 .wfm_size = 46770,
66 }, 100 },
67}; 101};
68 102
@@ -134,9 +168,8 @@ static u16 calc_img_cksum(u16 *start, int length)
134} 168}
135 169
136/* here we decode the incoming waveform file and populate metromem */ 170/* here we decode the incoming waveform file and populate metromem */
137#define EXP_WFORM_SIZE 47001 171static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
138static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t, 172 struct metronomefb_par *par)
139 u8 *frame_count)
140{ 173{
141 int tta; 174 int tta;
142 int wmta; 175 int wmta;
@@ -148,26 +181,31 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
148 int wfm_idx, owfm_idx; 181 int wfm_idx, owfm_idx;
149 int mem_idx = 0; 182 int mem_idx = 0;
150 struct waveform_hdr *wfm_hdr; 183 struct waveform_hdr *wfm_hdr;
184 u8 *metromem = par->metromem_wfm;
185 struct device *dev = par->info->dev;
151 186
152 if (size != EXP_WFORM_SIZE) { 187 if (user_wfm_size)
153 printk(KERN_ERR "Error: unexpected size %d != %d\n", size, 188 epd_frame_table[par->dt].wfm_size = user_wfm_size;
154 EXP_WFORM_SIZE); 189
190 if (size != epd_frame_table[par->dt].wfm_size) {
191 dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
192 epd_frame_table[par->dt].wfm_size);
155 return -EINVAL; 193 return -EINVAL;
156 } 194 }
157 195
158 wfm_hdr = (struct waveform_hdr *) mem; 196 wfm_hdr = (struct waveform_hdr *) mem;
159 197
160 if (wfm_hdr->fvsn != 1) { 198 if (wfm_hdr->fvsn != 1) {
161 printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn); 199 dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
162 return -EINVAL; 200 return -EINVAL;
163 } 201 }
164 if (wfm_hdr->luts != 0) { 202 if (wfm_hdr->luts != 0) {
165 printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts); 203 dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
166 return -EINVAL; 204 return -EINVAL;
167 } 205 }
168 cksum = calc_cksum(32, 47, mem); 206 cksum = calc_cksum(32, 47, mem);
169 if (cksum != wfm_hdr->wfm_cs) { 207 if (cksum != wfm_hdr->wfm_cs) {
170 printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum, 208 dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
171 wfm_hdr->wfm_cs); 209 wfm_hdr->wfm_cs);
172 return -EINVAL; 210 return -EINVAL;
173 } 211 }
@@ -175,7 +213,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
175 wfm_hdr->trc += 1; 213 wfm_hdr->trc += 1;
176 for (i = 0; i < 5; i++) { 214 for (i = 0; i < 5; i++) {
177 if (*(wfm_hdr->stuff2a + i) != 0) { 215 if (*(wfm_hdr->stuff2a + i) != 0) {
178 printk(KERN_ERR "Error: unexpected value in padding\n"); 216 dev_err(dev, "Error: unexpected value in padding\n");
179 return -EINVAL; 217 return -EINVAL;
180 } 218 }
181 } 219 }
@@ -200,7 +238,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
200 return -EINVAL; 238 return -EINVAL;
201 cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem); 239 cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
202 if (cksum != mem[cksum_idx]) { 240 if (cksum != mem[cksum_idx]) {
203 printk(KERN_ERR "Error: bad temperature range table cksum" 241 dev_err(dev, "Error: bad temperature range table cksum"
204 " %x != %x\n", cksum, mem[cksum_idx]); 242 " %x != %x\n", cksum, mem[cksum_idx]);
205 return -EINVAL; 243 return -EINVAL;
206 } 244 }
@@ -212,7 +250,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
212 return -EINVAL; 250 return -EINVAL;
213 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem); 251 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
214 if (cksum != mem[cksum_idx]) { 252 if (cksum != mem[cksum_idx]) {
215 printk(KERN_ERR "Error: bad mode table address cksum" 253 dev_err(dev, "Error: bad mode table address cksum"
216 " %x != %x\n", cksum, mem[cksum_idx]); 254 " %x != %x\n", cksum, mem[cksum_idx]);
217 return -EINVAL; 255 return -EINVAL;
218 } 256 }
@@ -224,7 +262,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
224 return -EINVAL; 262 return -EINVAL;
225 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem); 263 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
226 if (cksum != mem[cksum_idx]) { 264 if (cksum != mem[cksum_idx]) {
227 printk(KERN_ERR "Error: bad temperature table address cksum" 265 dev_err(dev, "Error: bad temperature table address cksum"
228 " %x != %x\n", cksum, mem[cksum_idx]); 266 " %x != %x\n", cksum, mem[cksum_idx]);
229 return -EINVAL; 267 return -EINVAL;
230 } 268 }
@@ -259,11 +297,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
259 return -EINVAL; 297 return -EINVAL;
260 cksum = calc_cksum(owfm_idx, cksum_idx, mem); 298 cksum = calc_cksum(owfm_idx, cksum_idx, mem);
261 if (cksum != mem[cksum_idx]) { 299 if (cksum != mem[cksum_idx]) {
262 printk(KERN_ERR "Error: bad waveform data cksum" 300 dev_err(dev, "Error: bad waveform data cksum"
263 " %x != %x\n", cksum, mem[cksum_idx]); 301 " %x != %x\n", cksum, mem[cksum_idx]);
264 return -EINVAL; 302 return -EINVAL;
265 } 303 }
266 *frame_count = (mem_idx/64); 304 par->frame_count = (mem_idx/64);
267 305
268 return 0; 306 return 0;
269} 307}
@@ -274,15 +312,12 @@ static int metronome_display_cmd(struct metronomefb_par *par)
274 u16 cs; 312 u16 cs;
275 u16 opcode; 313 u16 opcode;
276 static u8 borderval; 314 static u8 borderval;
277 u8 *ptr;
278 315
279 /* setup display command 316 /* setup display command
280 we can't immediately set the opcode since the controller 317 we can't immediately set the opcode since the controller
281 will try parse the command before we've set it all up 318 will try parse the command before we've set it all up
282 so we just set cs here and set the opcode at the end */ 319 so we just set cs here and set the opcode at the end */
283 320
284 ptr = par->metromem;
285
286 if (par->metromem_cmd->opcode == 0xCC40) 321 if (par->metromem_cmd->opcode == 0xCC40)
287 opcode = cs = 0xCC41; 322 opcode = cs = 0xCC41;
288 else 323 else
@@ -335,44 +370,17 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
335 370
336static int __devinit metronome_config_cmd(struct metronomefb_par *par) 371static int __devinit metronome_config_cmd(struct metronomefb_par *par)
337{ 372{
338 int i;
339 u16 cs;
340
341 /* setup config command 373 /* setup config command
342 we can't immediately set the opcode since the controller 374 we can't immediately set the opcode since the controller
343 will try parse the command before we've set it all up 375 will try parse the command before we've set it all up */
344 so we just set cs here and set the opcode at the end */
345
346 cs = 0xCC10;
347
348 /* set the 12 args ( 8 bytes ) for config. see spec for meanings */
349 i = 0;
350 par->metromem_cmd->args[i] = 15 /* sdlew */
351 | 2 << 8 /* sdosz */
352 | 0 << 11 /* sdor */
353 | 0 << 12 /* sdces */
354 | 0 << 15; /* sdcer */
355 cs += par->metromem_cmd->args[i++];
356
357 par->metromem_cmd->args[i] = 42 /* gdspl */
358 | 1 << 8 /* gdr1 */
359 | 1 << 9 /* sdshr */
360 | 0 << 15; /* gdspp */
361 cs += par->metromem_cmd->args[i++];
362
363 par->metromem_cmd->args[i] = 18 /* gdspw */
364 | 0 << 15; /* dispc */
365 cs += par->metromem_cmd->args[i++];
366
367 par->metromem_cmd->args[i] = 599 /* vdlc */
368 | 0 << 11 /* dsi */
369 | 0 << 12; /* dsic */
370 cs += par->metromem_cmd->args[i++];
371 376
377 memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
378 sizeof(epd_frame_table[par->dt].config));
372 /* the rest are 0 */ 379 /* the rest are 0 */
373 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2); 380 memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
374 381
375 par->metromem_cmd->csum = cs; 382 par->metromem_cmd->csum = 0xCC10;
383 par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
376 par->metromem_cmd->opcode = 0xCC10; /* config cmd */ 384 par->metromem_cmd->opcode = 0xCC10; /* config cmd */
377 385
378 return par->board->met_wait_event(par); 386 return par->board->met_wait_event(par);
@@ -408,12 +416,9 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
408{ 416{
409 int res; 417 int res;
410 418
411 par->board->init_gpio_regs(par); 419 res = par->board->setup_io(par);
412 420 if (res)
413 par->board->init_lcdc_regs(par); 421 return res;
414
415 /* now that lcd is setup, setup dma descriptor */
416 par->board->post_dma_setup(par);
417 422
418 res = metronome_powerup_cmd(par); 423 res = metronome_powerup_cmd(par);
419 if (res) 424 if (res)
@@ -430,16 +435,16 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
430 435
431static void metronomefb_dpy_update(struct metronomefb_par *par) 436static void metronomefb_dpy_update(struct metronomefb_par *par)
432{ 437{
438 int fbsize;
433 u16 cksum; 439 u16 cksum;
434 unsigned char *buf = (unsigned char __force *)par->info->screen_base; 440 unsigned char *buf = (unsigned char __force *)par->info->screen_base;
435 441
442 fbsize = par->info->fix.smem_len;
436 /* copy from vm to metromem */ 443 /* copy from vm to metromem */
437 memcpy(par->metromem_img, buf, DPY_W*DPY_H); 444 memcpy(par->metromem_img, buf, fbsize);
438 445
439 cksum = calc_img_cksum((u16 *) par->metromem_img, 446 cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
440 (epd_frame_table[0].fw * DPY_H)/2); 447 *((u16 *)(par->metromem_img) + fbsize/2) = cksum;
441 *((u16 *)(par->metromem_img) +
442 (epd_frame_table[0].fw * DPY_H)/2) = cksum;
443 metronome_display_cmd(par); 448 metronome_display_cmd(par);
444} 449}
445 450
@@ -574,8 +579,10 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
574 unsigned char *videomemory; 579 unsigned char *videomemory;
575 struct metronomefb_par *par; 580 struct metronomefb_par *par;
576 const struct firmware *fw_entry; 581 const struct firmware *fw_entry;
577 int cmd_size, wfm_size, img_size, padding_size, totalsize;
578 int i; 582 int i;
583 int panel_type;
584 int fw, fh;
585 int epd_dt_index;
579 586
580 /* pick up board specific routines */ 587 /* pick up board specific routines */
581 board = dev->dev.platform_data; 588 board = dev->dev.platform_data;
@@ -586,96 +593,108 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
586 if (!try_module_get(board->owner)) 593 if (!try_module_get(board->owner))
587 return -ENODEV; 594 return -ENODEV;
588 595
596 info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
597 if (!info)
598 goto err;
599
589 /* we have two blocks of memory. 600 /* we have two blocks of memory.
590 info->screen_base which is vm, and is the fb used by apps. 601 info->screen_base which is vm, and is the fb used by apps.
591 par->metromem which is physically contiguous memory and 602 par->metromem which is physically contiguous memory and
592 contains the display controller commands, waveform, 603 contains the display controller commands, waveform,
593 processed image data and padding. this is the data pulled 604 processed image data and padding. this is the data pulled
594 by the device's LCD controller and pushed to Metronome */ 605 by the device's LCD controller and pushed to Metronome.
606 the metromem memory is allocated by the board driver and
607 is provided to us */
608
609 panel_type = board->get_panel_type();
610 switch (panel_type) {
611 case 6:
612 epd_dt_index = 0;
613 break;
614 case 8:
615 epd_dt_index = 1;
616 break;
617 case 97:
618 epd_dt_index = 2;
619 break;
620 default:
621 dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
622 epd_dt_index = 0;
623 break;
624 }
625
626 fw = epd_frame_table[epd_dt_index].fw;
627 fh = epd_frame_table[epd_dt_index].fh;
595 628
596 videomemorysize = (DPY_W*DPY_H); 629 /* we need to add a spare page because our csum caching scheme walks
630 * to the end of the page */
631 videomemorysize = PAGE_SIZE + (fw * fh);
597 videomemory = vmalloc(videomemorysize); 632 videomemory = vmalloc(videomemorysize);
598 if (!videomemory) 633 if (!videomemory)
599 return -ENOMEM; 634 goto err_fb_rel;
600 635
601 memset(videomemory, 0, videomemorysize); 636 memset(videomemory, 0, videomemorysize);
602 637
603 info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
604 if (!info)
605 goto err_vfree;
606
607 info->screen_base = (char __force __iomem *)videomemory; 638 info->screen_base = (char __force __iomem *)videomemory;
608 info->fbops = &metronomefb_ops; 639 info->fbops = &metronomefb_ops;
609 640
641 metronomefb_fix.line_length = fw;
642 metronomefb_var.xres = fw;
643 metronomefb_var.yres = fh;
644 metronomefb_var.xres_virtual = fw;
645 metronomefb_var.yres_virtual = fh;
610 info->var = metronomefb_var; 646 info->var = metronomefb_var;
611 info->fix = metronomefb_fix; 647 info->fix = metronomefb_fix;
612 info->fix.smem_len = videomemorysize; 648 info->fix.smem_len = videomemorysize;
613 par = info->par; 649 par = info->par;
614 par->info = info; 650 par->info = info;
615 par->board = board; 651 par->board = board;
652 par->dt = epd_dt_index;
616 init_waitqueue_head(&par->waitq); 653 init_waitqueue_head(&par->waitq);
617 654
618 /* this table caches per page csum values. */ 655 /* this table caches per page csum values. */
619 par->csum_table = vmalloc(videomemorysize/PAGE_SIZE); 656 par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
620 if (!par->csum_table) 657 if (!par->csum_table)
658 goto err_vfree;
659
660 /* the physical framebuffer that we use is setup by
661 * the platform device driver. It will provide us
662 * with cmd, wfm and image memory in a contiguous area. */
663 retval = board->setup_fb(par);
664 if (retval) {
665 dev_err(&dev->dev, "Failed to setup fb\n");
621 goto err_csum_table; 666 goto err_csum_table;
667 }
622 668
623 /* the metromem buffer is divided as follows: 669 /* after this point we should have a framebuffer */
624 command | CRC | padding 670 if ((!par->metromem_wfm) || (!par->metromem_img) ||
625 16kb waveform data | CRC | padding 671 (!par->metromem_dma)) {
626 image data | CRC 672 dev_err(&dev->dev, "fb access failure\n");
627 and an extra 256 bytes for dma descriptors 673 retval = -EINVAL;
628 eg: IW=832 IH=622 WS=128 674 goto err_csum_table;
629 */
630
631 cmd_size = 1 * epd_frame_table[0].fw;
632 wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1)
633 / epd_frame_table[0].fw) * epd_frame_table[0].fw;
634 img_size = epd_frame_table[0].fh * epd_frame_table[0].fw;
635 padding_size = 4 * epd_frame_table[0].fw;
636 totalsize = cmd_size + wfm_size + img_size + padding_size;
637 par->metromemsize = PAGE_ALIGN(totalsize + 256);
638 DPRINTK("desired memory size = %d\n", par->metromemsize);
639 dev->dev.coherent_dma_mask = 0xffffffffull;
640 par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize,
641 &par->metromem_dma, GFP_KERNEL);
642 if (!par->metromem) {
643 printk(KERN_ERR
644 "metronomefb: unable to allocate dma buffer\n");
645 goto err_vfree;
646 } 675 }
647 676
648 info->fix.smem_start = par->metromem_dma; 677 info->fix.smem_start = par->metromem_dma;
649 par->metromem_cmd = (struct metromem_cmd *) par->metromem;
650 par->metromem_wfm = par->metromem + cmd_size;
651 par->metromem_img = par->metromem + cmd_size + wfm_size;
652 par->metromem_img_csum = (u16 *) (par->metromem_img +
653 (epd_frame_table[0].fw * DPY_H));
654 DPRINTK("img offset=0x%x\n", cmd_size + wfm_size);
655 par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size
656 + wfm_size + img_size + padding_size);
657 par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
658 + img_size + padding_size;
659 678
660 /* load the waveform in. assume mode 3, temp 31 for now 679 /* load the waveform in. assume mode 3, temp 31 for now
661 a) request the waveform file from userspace 680 a) request the waveform file from userspace
662 b) process waveform and decode into metromem */ 681 b) process waveform and decode into metromem */
663 retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev); 682 retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
664 if (retval < 0) { 683 if (retval < 0) {
665 printk(KERN_ERR "metronomefb: couldn't get waveform\n"); 684 dev_err(&dev->dev, "Failed to get waveform\n");
666 goto err_dma_free; 685 goto err_csum_table;
667 } 686 }
668 687
669 retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 688 retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
670 par->metromem_wfm, 3, 31, &par->frame_count); 689 par);
671 release_firmware(fw_entry); 690 release_firmware(fw_entry);
672 if (retval < 0) { 691 if (retval < 0) {
673 printk(KERN_ERR "metronomefb: couldn't process waveform\n"); 692 dev_err(&dev->dev, "Failed processing waveform\n");
674 goto err_dma_free; 693 goto err_csum_table;
675 } 694 }
676 695
677 if (board->setup_irq(info)) 696 if (board->setup_irq(info))
678 goto err_dma_free; 697 goto err_csum_table;
679 698
680 retval = metronome_init_regs(par); 699 retval = metronome_init_regs(par);
681 if (retval < 0) 700 if (retval < 0)
@@ -688,8 +707,8 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
688 707
689 retval = fb_alloc_cmap(&info->cmap, 8, 0); 708 retval = fb_alloc_cmap(&info->cmap, 8, 0);
690 if (retval < 0) { 709 if (retval < 0) {
691 printk(KERN_ERR "Failed to allocate colormap\n"); 710 dev_err(&dev->dev, "Failed to allocate colormap\n");
692 goto err_fb_rel; 711 goto err_free_irq;
693 } 712 }
694 713
695 /* set cmap */ 714 /* set cmap */
@@ -704,7 +723,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
704 723
705 platform_set_drvdata(dev, info); 724 platform_set_drvdata(dev, info);
706 725
707 printk(KERN_INFO 726 dev_dbg(&dev->dev,
708 "fb%d: Metronome frame buffer device, using %dK of video" 727 "fb%d: Metronome frame buffer device, using %dK of video"
709 " memory\n", info->node, videomemorysize >> 10); 728 " memory\n", info->node, videomemorysize >> 10);
710 729
@@ -712,17 +731,15 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
712 731
713err_cmap: 732err_cmap:
714 fb_dealloc_cmap(&info->cmap); 733 fb_dealloc_cmap(&info->cmap);
715err_fb_rel:
716 framebuffer_release(info);
717err_free_irq: 734err_free_irq:
718 board->free_irq(info); 735 board->cleanup(par);
719err_dma_free:
720 dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
721 par->metromem_dma);
722err_csum_table: 736err_csum_table:
723 vfree(par->csum_table); 737 vfree(par->csum_table);
724err_vfree: 738err_vfree:
725 vfree(videomemory); 739 vfree(videomemory);
740err_fb_rel:
741 framebuffer_release(info);
742err:
726 module_put(board->owner); 743 module_put(board->owner);
727 return retval; 744 return retval;
728} 745}
@@ -733,15 +750,15 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
733 750
734 if (info) { 751 if (info) {
735 struct metronomefb_par *par = info->par; 752 struct metronomefb_par *par = info->par;
753
754 unregister_framebuffer(info);
736 fb_deferred_io_cleanup(info); 755 fb_deferred_io_cleanup(info);
737 dma_free_writecombine(&dev->dev, par->metromemsize,
738 par->metromem, par->metromem_dma);
739 fb_dealloc_cmap(&info->cmap); 756 fb_dealloc_cmap(&info->cmap);
757 par->board->cleanup(par);
740 vfree(par->csum_table); 758 vfree(par->csum_table);
741 unregister_framebuffer(info);
742 vfree((void __force *)info->screen_base); 759 vfree((void __force *)info->screen_base);
743 par->board->free_irq(info);
744 module_put(par->board->owner); 760 module_put(par->board->owner);
761 dev_dbg(&dev->dev, "calling release\n");
745 framebuffer_release(info); 762 framebuffer_release(info);
746 } 763 }
747 return 0; 764 return 0;
@@ -766,6 +783,9 @@ static void __exit metronomefb_exit(void)
766 platform_driver_unregister(&metronomefb_driver); 783 platform_driver_unregister(&metronomefb_driver);
767} 784}
768 785
786module_param(user_wfm_size, uint, 0);
787MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
788
769module_init(metronomefb_init); 789module_init(metronomefb_init);
770module_exit(metronomefb_exit); 790module_exit(metronomefb_exit);
771 791
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 5246b0402d76..bfb802d26d5a 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -201,7 +201,6 @@ static int neoFindMode(int xres, int yres, int depth)
201 * 201 *
202 * Determine the closest clock frequency to the one requested. 202 * Determine the closest clock frequency to the one requested.
203 */ 203 */
204#define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */
205#define MAX_N 127 204#define MAX_N 127
206#define MAX_D 31 205#define MAX_D 31
207#define MAX_F 1 206#define MAX_F 1
@@ -211,27 +210,24 @@ static void neoCalcVCLK(const struct fb_info *info,
211{ 210{
212 int n, d, f; 211 int n, d, f;
213 int n_best = 0, d_best = 0, f_best = 0; 212 int n_best = 0, d_best = 0, f_best = 0;
214 long f_best_diff = (0x7ffff << 12); /* 20.12 */ 213 long f_best_diff = 0x7ffff;
215 long f_target = (freq << 12) / 1000; /* 20.12 */
216 214
217 for (f = 0; f <= MAX_F; f++) 215 for (f = 0; f <= MAX_F; f++)
218 for (n = 0; n <= MAX_N; n++) 216 for (d = 0; d <= MAX_D; d++)
219 for (d = 0; d <= MAX_D; d++) { 217 for (n = 0; n <= MAX_N; n++) {
220 long f_out; /* 20.12 */ 218 long f_out;
221 long f_diff; /* 20.12 */ 219 long f_diff;
222 220
223 f_out = 221 f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
224 ((((n + 1) << 12) / ((d + 222 f_diff = abs(f_out - freq);
225 1) * 223 if (f_diff <= f_best_diff) {
226 (1 << f))) >> 12)
227 * REF_FREQ;
228 f_diff = abs(f_out - f_target);
229 if (f_diff < f_best_diff) {
230 f_best_diff = f_diff; 224 f_best_diff = f_diff;
231 n_best = n; 225 n_best = n;
232 d_best = d; 226 d_best = d;
233 f_best = f; 227 f_best = f;
234 } 228 }
229 if (f_out > freq)
230 break;
235 } 231 }
236 232
237 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 || 233 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
@@ -248,11 +244,11 @@ static void neoCalcVCLK(const struct fb_info *info,
248 par->VCLK3Denominator = d_best; 244 par->VCLK3Denominator = d_best;
249 245
250#ifdef NEOFB_DEBUG 246#ifdef NEOFB_DEBUG
251 printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n", 247 printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
252 f_target >> 12, 248 freq,
253 par->VCLK3NumeratorLow, 249 par->VCLK3NumeratorLow,
254 par->VCLK3NumeratorHigh, 250 par->VCLK3NumeratorHigh,
255 par->VCLK3Denominator, f_best_diff >> 12); 251 par->VCLK3Denominator, f_best_diff);
256#endif 252#endif
257} 253}
258 254
@@ -263,15 +259,20 @@ static void neoCalcVCLK(const struct fb_info *info,
263 */ 259 */
264 260
265static int vgaHWInit(const struct fb_var_screeninfo *var, 261static int vgaHWInit(const struct fb_var_screeninfo *var,
266 const struct fb_info *info, 262 struct neofb_par *par)
267 struct neofb_par *par, struct xtimings *timings)
268{ 263{
264 int hsync_end = var->xres + var->right_margin + var->hsync_len;
265 int htotal = (hsync_end + var->left_margin) >> 3;
266 int vsync_start = var->yres + var->lower_margin;
267 int vsync_end = vsync_start + var->vsync_len;
268 int vtotal = vsync_end + var->upper_margin;
269
269 par->MiscOutReg = 0x23; 270 par->MiscOutReg = 0x23;
270 271
271 if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT)) 272 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
272 par->MiscOutReg |= 0x40; 273 par->MiscOutReg |= 0x40;
273 274
274 if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT)) 275 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
275 par->MiscOutReg |= 0x80; 276 par->MiscOutReg |= 0x80;
276 277
277 /* 278 /*
@@ -286,25 +287,25 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
286 /* 287 /*
287 * CRTC Controller 288 * CRTC Controller
288 */ 289 */
289 par->CRTC[0] = (timings->HTotal >> 3) - 5; 290 par->CRTC[0] = htotal - 5;
290 par->CRTC[1] = (timings->HDisplay >> 3) - 1; 291 par->CRTC[1] = (var->xres >> 3) - 1;
291 par->CRTC[2] = (timings->HDisplay >> 3) - 1; 292 par->CRTC[2] = (var->xres >> 3) - 1;
292 par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80; 293 par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
293 par->CRTC[4] = (timings->HSyncStart >> 3); 294 par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
294 par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2) 295 par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
295 | (((timings->HSyncEnd >> 3)) & 0x1F); 296 | (((hsync_end >> 3)) & 0x1F);
296 par->CRTC[6] = (timings->VTotal - 2) & 0xFF; 297 par->CRTC[6] = (vtotal - 2) & 0xFF;
297 par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8) 298 par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
298 | (((timings->VDisplay - 1) & 0x100) >> 7) 299 | (((var->yres - 1) & 0x100) >> 7)
299 | ((timings->VSyncStart & 0x100) >> 6) 300 | ((vsync_start & 0x100) >> 6)
300 | (((timings->VDisplay - 1) & 0x100) >> 5) 301 | (((var->yres - 1) & 0x100) >> 5)
301 | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4) 302 | 0x10 | (((vtotal - 2) & 0x200) >> 4)
302 | (((timings->VDisplay - 1) & 0x200) >> 3) 303 | (((var->yres - 1) & 0x200) >> 3)
303 | ((timings->VSyncStart & 0x200) >> 2); 304 | ((vsync_start & 0x200) >> 2);
304 par->CRTC[8] = 0x00; 305 par->CRTC[8] = 0x00;
305 par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40; 306 par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
306 307
307 if (timings->dblscan) 308 if (var->vmode & FB_VMODE_DOUBLE)
308 par->CRTC[9] |= 0x80; 309 par->CRTC[9] |= 0x80;
309 310
310 par->CRTC[10] = 0x00; 311 par->CRTC[10] = 0x00;
@@ -313,13 +314,13 @@ static int vgaHWInit(const struct fb_var_screeninfo *var,
313 par->CRTC[13] = 0x00; 314 par->CRTC[13] = 0x00;
314 par->CRTC[14] = 0x00; 315 par->CRTC[14] = 0x00;
315 par->CRTC[15] = 0x00; 316 par->CRTC[15] = 0x00;
316 par->CRTC[16] = timings->VSyncStart & 0xFF; 317 par->CRTC[16] = vsync_start & 0xFF;
317 par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20; 318 par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
318 par->CRTC[18] = (timings->VDisplay - 1) & 0xFF; 319 par->CRTC[18] = (var->yres - 1) & 0xFF;
319 par->CRTC[19] = var->xres_virtual >> 4; 320 par->CRTC[19] = var->xres_virtual >> 4;
320 par->CRTC[20] = 0x00; 321 par->CRTC[20] = 0x00;
321 par->CRTC[21] = (timings->VDisplay - 1) & 0xFF; 322 par->CRTC[21] = (var->yres - 1) & 0xFF;
322 par->CRTC[22] = (timings->VTotal - 1) & 0xFF; 323 par->CRTC[22] = (vtotal - 1) & 0xFF;
323 par->CRTC[23] = 0xC3; 324 par->CRTC[23] = 0xC3;
324 par->CRTC[24] = 0xFF; 325 par->CRTC[24] = 0xFF;
325 326
@@ -425,11 +426,11 @@ static void vgaHWProtect(int on)
425{ 426{
426 unsigned char tmp; 427 unsigned char tmp;
427 428
429 tmp = vga_rseq(NULL, 0x01);
428 if (on) { 430 if (on) {
429 /* 431 /*
430 * Turn off screen and disable sequencer. 432 * Turn off screen and disable sequencer.
431 */ 433 */
432 tmp = vga_rseq(NULL, 0x01);
433 vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */ 434 vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */
434 vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */ 435 vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */
435 436
@@ -438,7 +439,6 @@ static void vgaHWProtect(int on)
438 /* 439 /*
439 * Reenable sequencer, then turn on screen. 440 * Reenable sequencer, then turn on screen.
440 */ 441 */
441 tmp = vga_rseq(NULL, 0x01);
442 vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */ 442 vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */
443 vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */ 443 vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */
444 444
@@ -483,7 +483,8 @@ static inline int neo2200_sync(struct fb_info *info)
483{ 483{
484 struct neofb_par *par = info->par; 484 struct neofb_par *par = info->par;
485 485
486 while (readl(&par->neo2200->bltStat) & 1); 486 while (readl(&par->neo2200->bltStat) & 1)
487 cpu_relax();
487 return 0; 488 return 0;
488} 489}
489 490
@@ -556,14 +557,12 @@ neofb_open(struct fb_info *info, int user)
556{ 557{
557 struct neofb_par *par = info->par; 558 struct neofb_par *par = info->par;
558 559
559 mutex_lock(&par->open_lock);
560 if (!par->ref_count) { 560 if (!par->ref_count) {
561 memset(&par->state, 0, sizeof(struct vgastate)); 561 memset(&par->state, 0, sizeof(struct vgastate));
562 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; 562 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
563 save_vga(&par->state); 563 save_vga(&par->state);
564 } 564 }
565 par->ref_count++; 565 par->ref_count++;
566 mutex_unlock(&par->open_lock);
567 566
568 return 0; 567 return 0;
569} 568}
@@ -573,16 +572,13 @@ neofb_release(struct fb_info *info, int user)
573{ 572{
574 struct neofb_par *par = info->par; 573 struct neofb_par *par = info->par;
575 574
576 mutex_lock(&par->open_lock); 575 if (!par->ref_count)
577 if (!par->ref_count) {
578 mutex_unlock(&par->open_lock);
579 return -EINVAL; 576 return -EINVAL;
580 } 577
581 if (par->ref_count == 1) { 578 if (par->ref_count == 1) {
582 restore_vga(&par->state); 579 restore_vga(&par->state);
583 } 580 }
584 par->ref_count--; 581 par->ref_count--;
585 mutex_unlock(&par->open_lock);
586 582
587 return 0; 583 return 0;
588} 584}
@@ -591,34 +587,14 @@ static int
591neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 587neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
592{ 588{
593 struct neofb_par *par = info->par; 589 struct neofb_par *par = info->par;
594 unsigned int pixclock = var->pixclock;
595 struct xtimings timings;
596 int memlen, vramlen; 590 int memlen, vramlen;
597 int mode_ok = 0; 591 int mode_ok = 0;
598 592
599 DBG("neofb_check_var"); 593 DBG("neofb_check_var");
600 594
601 if (!pixclock) 595 if (PICOS2KHZ(var->pixclock) > par->maxClock)
602 pixclock = 10000; /* 10ns = 100MHz */
603 timings.pixclock = 1000000000 / pixclock;
604 if (timings.pixclock < 1)
605 timings.pixclock = 1;
606
607 if (timings.pixclock > par->maxClock)
608 return -EINVAL; 596 return -EINVAL;
609 597
610 timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
611 timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
612 timings.HDisplay = var->xres;
613 timings.HSyncStart = timings.HDisplay + var->right_margin;
614 timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
615 timings.HTotal = timings.HSyncEnd + var->left_margin;
616 timings.VDisplay = var->yres;
617 timings.VSyncStart = timings.VDisplay + var->lower_margin;
618 timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
619 timings.VTotal = timings.VSyncEnd + var->upper_margin;
620 timings.sync = var->sync;
621
622 /* Is the mode larger than the LCD panel? */ 598 /* Is the mode larger than the LCD panel? */
623 if (par->internal_display && 599 if (par->internal_display &&
624 ((var->xres > par->NeoPanelWidth) || 600 ((var->xres > par->NeoPanelWidth) ||
@@ -666,10 +642,10 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
666 var->blue.msb_right = 0; 642 var->blue.msb_right = 0;
667 var->transp.msb_right = 0; 643 var->transp.msb_right = 0;
668 644
645 var->transp.offset = 0;
646 var->transp.length = 0;
669 switch (var->bits_per_pixel) { 647 switch (var->bits_per_pixel) {
670 case 8: /* PSEUDOCOLOUR, 256 */ 648 case 8: /* PSEUDOCOLOUR, 256 */
671 var->transp.offset = 0;
672 var->transp.length = 0;
673 var->red.offset = 0; 649 var->red.offset = 0;
674 var->red.length = 8; 650 var->red.length = 8;
675 var->green.offset = 0; 651 var->green.offset = 0;
@@ -679,8 +655,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
679 break; 655 break;
680 656
681 case 16: /* DIRECTCOLOUR, 64k */ 657 case 16: /* DIRECTCOLOUR, 64k */
682 var->transp.offset = 0;
683 var->transp.length = 0;
684 var->red.offset = 11; 658 var->red.offset = 11;
685 var->red.length = 5; 659 var->red.length = 5;
686 var->green.offset = 5; 660 var->green.offset = 5;
@@ -690,8 +664,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
690 break; 664 break;
691 665
692 case 24: /* TRUECOLOUR, 16m */ 666 case 24: /* TRUECOLOUR, 16m */
693 var->transp.offset = 0;
694 var->transp.length = 0;
695 var->red.offset = 16; 667 var->red.offset = 16;
696 var->red.length = 8; 668 var->red.length = 8;
697 var->green.offset = 8; 669 var->green.offset = 8;
@@ -722,8 +694,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
722 if (vramlen > 4 * 1024 * 1024) 694 if (vramlen > 4 * 1024 * 1024)
723 vramlen = 4 * 1024 * 1024; 695 vramlen = 4 * 1024 * 1024;
724 696
725 if (var->yres_virtual < var->yres)
726 var->yres_virtual = var->yres;
727 if (var->xres_virtual < var->xres) 697 if (var->xres_virtual < var->xres)
728 var->xres_virtual = var->xres; 698 var->xres_virtual = var->xres;
729 699
@@ -740,8 +710,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
740 if it was possible. We should return -EINVAL, but I disagree */ 710 if it was possible. We should return -EINVAL, but I disagree */
741 if (var->yres_virtual < var->yres) 711 if (var->yres_virtual < var->yres)
742 var->yres = var->yres_virtual; 712 var->yres = var->yres_virtual;
743 if (var->xres_virtual < var->xres)
744 var->xres = var->xres_virtual;
745 if (var->xoffset + var->xres > var->xres_virtual) 713 if (var->xoffset + var->xres > var->xres_virtual)
746 var->xoffset = var->xres_virtual - var->xres; 714 var->xoffset = var->xres_virtual - var->xres;
747 if (var->yoffset + var->yres > var->yres_virtual) 715 if (var->yoffset + var->yres > var->yres_virtual)
@@ -759,11 +727,11 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
759static int neofb_set_par(struct fb_info *info) 727static int neofb_set_par(struct fb_info *info)
760{ 728{
761 struct neofb_par *par = info->par; 729 struct neofb_par *par = info->par;
762 struct xtimings timings;
763 unsigned char temp; 730 unsigned char temp;
764 int i, clock_hi = 0; 731 int i, clock_hi = 0;
765 int lcd_stretch; 732 int lcd_stretch;
766 int hoffset, voffset; 733 int hoffset, voffset;
734 int vsync_start, vtotal;
767 735
768 DBG("neofb_set_par"); 736 DBG("neofb_set_par");
769 737
@@ -771,28 +739,15 @@ static int neofb_set_par(struct fb_info *info)
771 739
772 vgaHWProtect(1); /* Blank the screen */ 740 vgaHWProtect(1); /* Blank the screen */
773 741
774 timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE; 742 vsync_start = info->var.yres + info->var.lower_margin;
775 timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED; 743 vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
776 timings.HDisplay = info->var.xres;
777 timings.HSyncStart = timings.HDisplay + info->var.right_margin;
778 timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len;
779 timings.HTotal = timings.HSyncEnd + info->var.left_margin;
780 timings.VDisplay = info->var.yres;
781 timings.VSyncStart = timings.VDisplay + info->var.lower_margin;
782 timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len;
783 timings.VTotal = timings.VSyncEnd + info->var.upper_margin;
784 timings.sync = info->var.sync;
785 timings.pixclock = PICOS2KHZ(info->var.pixclock);
786
787 if (timings.pixclock < 1)
788 timings.pixclock = 1;
789 744
790 /* 745 /*
791 * This will allocate the datastructure and initialize all of the 746 * This will allocate the datastructure and initialize all of the
792 * generic VGA registers. 747 * generic VGA registers.
793 */ 748 */
794 749
795 if (vgaHWInit(&info->var, info, par, &timings)) 750 if (vgaHWInit(&info->var, par))
796 return -EINVAL; 751 return -EINVAL;
797 752
798 /* 753 /*
@@ -831,10 +786,10 @@ static int neofb_set_par(struct fb_info *info)
831 par->ExtCRTDispAddr = 0x10; 786 par->ExtCRTDispAddr = 0x10;
832 787
833 /* Vertical Extension */ 788 /* Vertical Extension */
834 par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10) 789 par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
835 | (((timings.VDisplay - 1) & 0x400) >> 9) 790 | (((info->var.yres - 1) & 0x400) >> 9)
836 | (((timings.VSyncStart) & 0x400) >> 8) 791 | (((vsync_start) & 0x400) >> 8)
837 | (((timings.VSyncStart) & 0x400) >> 7); 792 | (((vsync_start) & 0x400) >> 7);
838 793
839 /* Fast write bursts on unless disabled. */ 794 /* Fast write bursts on unless disabled. */
840 if (par->pci_burst) 795 if (par->pci_burst)
@@ -995,7 +950,7 @@ static int neofb_set_par(struct fb_info *info)
995 * Calculate the VCLK that most closely matches the requested dot 950 * Calculate the VCLK that most closely matches the requested dot
996 * clock. 951 * clock.
997 */ 952 */
998 neoCalcVCLK(info, par, timings.pixclock); 953 neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
999 954
1000 /* Since we program the clocks ourselves, always use VCLK3. */ 955 /* Since we program the clocks ourselves, always use VCLK3. */
1001 par->MiscOutReg |= 0x0C; 956 par->MiscOutReg |= 0x0C;
@@ -1217,8 +1172,11 @@ static int neofb_set_par(struct fb_info *info)
1217 return 0; 1172 return 0;
1218} 1173}
1219 1174
1220static void neofb_update_start(struct fb_info *info, 1175/*
1221 struct fb_var_screeninfo *var) 1176 * Pan or Wrap the Display
1177 */
1178static int neofb_pan_display(struct fb_var_screeninfo *var,
1179 struct fb_info *info)
1222{ 1180{
1223 struct neofb_par *par = info->par; 1181 struct neofb_par *par = info->par;
1224 struct vgastate *state = &par->state; 1182 struct vgastate *state = &par->state;
@@ -1247,35 +1205,7 @@ static void neofb_update_start(struct fb_info *info,
1247 vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); 1205 vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
1248 1206
1249 neoLock(state); 1207 neoLock(state);
1250}
1251 1208
1252/*
1253 * Pan or Wrap the Display
1254 */
1255static int neofb_pan_display(struct fb_var_screeninfo *var,
1256 struct fb_info *info)
1257{
1258 u_int y_bottom;
1259
1260 y_bottom = var->yoffset;
1261
1262 if (!(var->vmode & FB_VMODE_YWRAP))
1263 y_bottom += var->yres;
1264
1265 if (var->xoffset > (var->xres_virtual - var->xres))
1266 return -EINVAL;
1267 if (y_bottom > info->var.yres_virtual)
1268 return -EINVAL;
1269
1270 neofb_update_start(info, var);
1271
1272 info->var.xoffset = var->xoffset;
1273 info->var.yoffset = var->yoffset;
1274
1275 if (var->vmode & FB_VMODE_YWRAP)
1276 info->var.vmode |= FB_VMODE_YWRAP;
1277 else
1278 info->var.vmode &= ~FB_VMODE_YWRAP;
1279 return 0; 1209 return 0;
1280} 1210}
1281 1211
@@ -1927,9 +1857,6 @@ static int __devinit neo_init_hw(struct fb_info *info)
1927 int maxClock = 65000; 1857 int maxClock = 65000;
1928 int CursorMem = 1024; 1858 int CursorMem = 1024;
1929 int CursorOff = 0x100; 1859 int CursorOff = 0x100;
1930 int linearSize = 1024;
1931 int maxWidth = 1024;
1932 int maxHeight = 1024;
1933 1860
1934 DBG("neo_init_hw"); 1861 DBG("neo_init_hw");
1935 1862
@@ -1948,81 +1875,52 @@ static int __devinit neo_init_hw(struct fb_info *info)
1948 case FB_ACCEL_NEOMAGIC_NM2070: 1875 case FB_ACCEL_NEOMAGIC_NM2070:
1949 videoRam = 896; 1876 videoRam = 896;
1950 maxClock = 65000; 1877 maxClock = 65000;
1951 CursorMem = 2048;
1952 CursorOff = 0x100;
1953 linearSize = 1024;
1954 maxWidth = 1024;
1955 maxHeight = 1024;
1956 break; 1878 break;
1957 case FB_ACCEL_NEOMAGIC_NM2090: 1879 case FB_ACCEL_NEOMAGIC_NM2090:
1958 case FB_ACCEL_NEOMAGIC_NM2093: 1880 case FB_ACCEL_NEOMAGIC_NM2093:
1959 videoRam = 1152;
1960 maxClock = 80000;
1961 CursorMem = 2048;
1962 CursorOff = 0x100;
1963 linearSize = 2048;
1964 maxWidth = 1024;
1965 maxHeight = 1024;
1966 break;
1967 case FB_ACCEL_NEOMAGIC_NM2097: 1881 case FB_ACCEL_NEOMAGIC_NM2097:
1968 videoRam = 1152; 1882 videoRam = 1152;
1969 maxClock = 80000; 1883 maxClock = 80000;
1970 CursorMem = 1024;
1971 CursorOff = 0x100;
1972 linearSize = 2048;
1973 maxWidth = 1024;
1974 maxHeight = 1024;
1975 break; 1884 break;
1976 case FB_ACCEL_NEOMAGIC_NM2160: 1885 case FB_ACCEL_NEOMAGIC_NM2160:
1977 videoRam = 2048; 1886 videoRam = 2048;
1978 maxClock = 90000; 1887 maxClock = 90000;
1979 CursorMem = 1024;
1980 CursorOff = 0x100;
1981 linearSize = 2048;
1982 maxWidth = 1024;
1983 maxHeight = 1024;
1984 break; 1888 break;
1985 case FB_ACCEL_NEOMAGIC_NM2200: 1889 case FB_ACCEL_NEOMAGIC_NM2200:
1986 videoRam = 2560; 1890 videoRam = 2560;
1987 maxClock = 110000; 1891 maxClock = 110000;
1988 CursorMem = 1024;
1989 CursorOff = 0x1000;
1990 linearSize = 4096;
1991 maxWidth = 1280;
1992 maxHeight = 1024; /* ???? */
1993
1994 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
1995 break; 1892 break;
1996 case FB_ACCEL_NEOMAGIC_NM2230: 1893 case FB_ACCEL_NEOMAGIC_NM2230:
1997 videoRam = 3008; 1894 videoRam = 3008;
1998 maxClock = 110000; 1895 maxClock = 110000;
1999 CursorMem = 1024;
2000 CursorOff = 0x1000;
2001 linearSize = 4096;
2002 maxWidth = 1280;
2003 maxHeight = 1024; /* ???? */
2004
2005 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2006 break; 1896 break;
2007 case FB_ACCEL_NEOMAGIC_NM2360: 1897 case FB_ACCEL_NEOMAGIC_NM2360:
2008 videoRam = 4096; 1898 videoRam = 4096;
2009 maxClock = 110000; 1899 maxClock = 110000;
2010 CursorMem = 1024;
2011 CursorOff = 0x1000;
2012 linearSize = 4096;
2013 maxWidth = 1280;
2014 maxHeight = 1024; /* ???? */
2015
2016 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2017 break; 1900 break;
2018 case FB_ACCEL_NEOMAGIC_NM2380: 1901 case FB_ACCEL_NEOMAGIC_NM2380:
2019 videoRam = 6144; 1902 videoRam = 6144;
2020 maxClock = 110000; 1903 maxClock = 110000;
1904 break;
1905 }
1906 switch (info->fix.accel) {
1907 case FB_ACCEL_NEOMAGIC_NM2070:
1908 case FB_ACCEL_NEOMAGIC_NM2090:
1909 case FB_ACCEL_NEOMAGIC_NM2093:
1910 CursorMem = 2048;
1911 CursorOff = 0x100;
1912 break;
1913 case FB_ACCEL_NEOMAGIC_NM2097:
1914 case FB_ACCEL_NEOMAGIC_NM2160:
1915 CursorMem = 1024;
1916 CursorOff = 0x100;
1917 break;
1918 case FB_ACCEL_NEOMAGIC_NM2200:
1919 case FB_ACCEL_NEOMAGIC_NM2230:
1920 case FB_ACCEL_NEOMAGIC_NM2360:
1921 case FB_ACCEL_NEOMAGIC_NM2380:
2021 CursorMem = 1024; 1922 CursorMem = 1024;
2022 CursorOff = 0x1000; 1923 CursorOff = 0x1000;
2023 linearSize = 8192;
2024 maxWidth = 1280;
2025 maxHeight = 1024; /* ???? */
2026 1924
2027 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase; 1925 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2028 break; 1926 break;
@@ -2036,7 +1934,7 @@ static int __devinit neo_init_hw(struct fb_info *info)
2036*/ 1934*/
2037 par->maxClock = maxClock; 1935 par->maxClock = maxClock;
2038 par->cursorOff = CursorOff; 1936 par->cursorOff = CursorOff;
2039 return ((videoRam * 1024)); 1937 return videoRam * 1024;
2040} 1938}
2041 1939
2042 1940
@@ -2055,7 +1953,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
2055 1953
2056 info->fix.accel = id->driver_data; 1954 info->fix.accel = id->driver_data;
2057 1955
2058 mutex_init(&par->open_lock);
2059 par->pci_burst = !nopciburst; 1956 par->pci_burst = !nopciburst;
2060 par->lcd_stretch = !nostretch; 1957 par->lcd_stretch = !nostretch;
2061 par->libretto = libretto; 1958 par->libretto = libretto;
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index d7b3dcc0dc43..e1d9eeb1aeaf 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -47,6 +47,7 @@ enum {
47 cmap_M3B, /* ATI Rage Mobility M3 Head B */ 47 cmap_M3B, /* ATI Rage Mobility M3 Head B */
48 cmap_radeon, /* ATI Radeon */ 48 cmap_radeon, /* ATI Radeon */
49 cmap_gxt2000, /* IBM GXT2000 */ 49 cmap_gxt2000, /* IBM GXT2000 */
50 cmap_avivo, /* ATI R5xx */
50}; 51};
51 52
52struct offb_par { 53struct offb_par {
@@ -58,26 +59,36 @@ struct offb_par {
58 59
59struct offb_par default_par; 60struct offb_par default_par;
60 61
61 /*
62 * Interface used by the world
63 */
64
65static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
66 u_int transp, struct fb_info *info);
67static int offb_blank(int blank, struct fb_info *info);
68
69#ifdef CONFIG_PPC32 62#ifdef CONFIG_PPC32
70extern boot_infos_t *boot_infos; 63extern boot_infos_t *boot_infos;
71#endif 64#endif
72 65
73static struct fb_ops offb_ops = { 66/* Definitions used by the Avivo palette hack */
74 .owner = THIS_MODULE, 67#define AVIVO_DC_LUT_RW_SELECT 0x6480
75 .fb_setcolreg = offb_setcolreg, 68#define AVIVO_DC_LUT_RW_MODE 0x6484
76 .fb_blank = offb_blank, 69#define AVIVO_DC_LUT_RW_INDEX 0x6488
77 .fb_fillrect = cfb_fillrect, 70#define AVIVO_DC_LUT_SEQ_COLOR 0x648c
78 .fb_copyarea = cfb_copyarea, 71#define AVIVO_DC_LUT_PWL_DATA 0x6490
79 .fb_imageblit = cfb_imageblit, 72#define AVIVO_DC_LUT_30_COLOR 0x6494
80}; 73#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498
74#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c
75#define AVIVO_DC_LUT_AUTOFILL 0x64a0
76
77#define AVIVO_DC_LUTA_CONTROL 0x64c0
78#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4
79#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8
80#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc
81#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0
82#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
83#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
84
85#define AVIVO_DC_LUTB_CONTROL 0x6cc0
86#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4
87#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8
88#define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc
89#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0
90#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4
91#define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8
81 92
82 /* 93 /*
83 * Set a single color register. The values supplied are already 94 * Set a single color register. The values supplied are already
@@ -160,6 +171,17 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
160 out_le32(((unsigned __iomem *) par->cmap_adr) + regno, 171 out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
161 (red << 16 | green << 8 | blue)); 172 (red << 16 | green << 8 | blue));
162 break; 173 break;
174 case cmap_avivo:
175 /* Write to both LUTs for now */
176 writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
177 writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
178 writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
179 par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
180 writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
181 writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
182 writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
183 par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
184 break;
163 } 185 }
164 186
165 return 0; 187 return 0;
@@ -216,12 +238,59 @@ static int offb_blank(int blank, struct fb_info *info)
216 out_le32(((unsigned __iomem *) par->cmap_adr) + i, 238 out_le32(((unsigned __iomem *) par->cmap_adr) + i,
217 0); 239 0);
218 break; 240 break;
241 case cmap_avivo:
242 writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
243 writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
244 writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
245 writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
246 writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
247 writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
248 break;
219 } 249 }
220 } else 250 } else
221 fb_set_cmap(&info->cmap, info); 251 fb_set_cmap(&info->cmap, info);
222 return 0; 252 return 0;
223} 253}
224 254
255static int offb_set_par(struct fb_info *info)
256{
257 struct offb_par *par = (struct offb_par *) info->par;
258
259 /* On avivo, initialize palette control */
260 if (par->cmap_type == cmap_avivo) {
261 writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
262 writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
263 writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
264 writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
265 writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
266 writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
267 writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
268 writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
269 writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
270 writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
271 writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
272 writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
273 writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
274 writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
275 writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
276 writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
277 writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
278 writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
279 writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
280 writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
281 }
282 return 0;
283}
284
285static struct fb_ops offb_ops = {
286 .owner = THIS_MODULE,
287 .fb_setcolreg = offb_setcolreg,
288 .fb_set_par = offb_set_par,
289 .fb_blank = offb_blank,
290 .fb_fillrect = cfb_fillrect,
291 .fb_copyarea = cfb_copyarea,
292 .fb_imageblit = cfb_imageblit,
293};
225 294
226static void __iomem *offb_map_reg(struct device_node *np, int index, 295static void __iomem *offb_map_reg(struct device_node *np, int index,
227 unsigned long offset, unsigned long size) 296 unsigned long offset, unsigned long size)
@@ -245,6 +314,59 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
245 return ioremap(taddr + offset, size); 314 return ioremap(taddr + offset, size);
246} 315}
247 316
317static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
318 const char *name, unsigned long address)
319{
320 struct offb_par *par = (struct offb_par *) info->par;
321
322 if (dp && !strncmp(name, "ATY,Rage128", 11)) {
323 par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
324 if (par->cmap_adr)
325 par->cmap_type = cmap_r128;
326 } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
327 || !strncmp(name, "ATY,RageM3p12A", 14))) {
328 par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
329 if (par->cmap_adr)
330 par->cmap_type = cmap_M3A;
331 } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
332 par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
333 if (par->cmap_adr)
334 par->cmap_type = cmap_M3B;
335 } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
336 par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
337 if (par->cmap_adr)
338 par->cmap_type = cmap_radeon;
339 } else if (!strncmp(name, "ATY,", 4)) {
340 unsigned long base = address & 0xff000000UL;
341 par->cmap_adr =
342 ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
343 par->cmap_data = par->cmap_adr + 1;
344 par->cmap_type = cmap_m64;
345 } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
346 of_device_is_compatible(dp, "pci1014,21c"))) {
347 par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
348 if (par->cmap_adr)
349 par->cmap_type = cmap_gxt2000;
350 } else if (dp && !strncmp(name, "vga,Display-", 12)) {
351 /* Look for AVIVO initialized by SLOF */
352 struct device_node *pciparent = of_get_parent(dp);
353 const u32 *vid, *did;
354 vid = of_get_property(pciparent, "vendor-id", NULL);
355 did = of_get_property(pciparent, "device-id", NULL);
356 /* This will match most R5xx */
357 if (vid && did && *vid == 0x1002 &&
358 ((*did >= 0x7100 && *did < 0x7800) ||
359 (*did >= 0x9400))) {
360 par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
361 if (par->cmap_adr)
362 par->cmap_type = cmap_avivo;
363 }
364 of_node_put(pciparent);
365 }
366 info->fix.visual = (par->cmap_type != cmap_unknown) ?
367 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
368}
369
248static void __init offb_init_fb(const char *name, const char *full_name, 370static void __init offb_init_fb(const char *name, const char *full_name,
249 int width, int height, int depth, 371 int width, int height, int depth,
250 int pitch, unsigned long address, 372 int pitch, unsigned long address,
@@ -283,6 +405,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
283 405
284 fix = &info->fix; 406 fix = &info->fix;
285 var = &info->var; 407 var = &info->var;
408 info->par = par;
286 409
287 strcpy(fix->id, "OFfb "); 410 strcpy(fix->id, "OFfb ");
288 strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb ")); 411 strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
@@ -298,39 +421,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
298 fix->type_aux = 0; 421 fix->type_aux = 0;
299 422
300 par->cmap_type = cmap_unknown; 423 par->cmap_type = cmap_unknown;
301 if (depth == 8) { 424 if (depth == 8)
302 if (dp && !strncmp(name, "ATY,Rage128", 11)) { 425 offb_init_palette_hacks(info, dp, name, address);
303 par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); 426 else
304 if (par->cmap_adr)
305 par->cmap_type = cmap_r128;
306 } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
307 || !strncmp(name, "ATY,RageM3p12A", 14))) {
308 par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
309 if (par->cmap_adr)
310 par->cmap_type = cmap_M3A;
311 } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
312 par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
313 if (par->cmap_adr)
314 par->cmap_type = cmap_M3B;
315 } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
316 par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
317 if (par->cmap_adr)
318 par->cmap_type = cmap_radeon;
319 } else if (!strncmp(name, "ATY,", 4)) {
320 unsigned long base = address & 0xff000000UL;
321 par->cmap_adr =
322 ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
323 par->cmap_data = par->cmap_adr + 1;
324 par->cmap_type = cmap_m64;
325 } else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
326 of_device_is_compatible(dp, "pci1014,21c"))) {
327 par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
328 if (par->cmap_adr)
329 par->cmap_type = cmap_gxt2000;
330 }
331 fix->visual = (par->cmap_type != cmap_unknown) ?
332 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
333 } else
334 fix->visual = FB_VISUAL_TRUECOLOR; 427 fix->visual = FB_VISUAL_TRUECOLOR;
335 428
336 var->xoffset = var->yoffset = 0; 429 var->xoffset = var->yoffset = 0;
@@ -395,7 +488,6 @@ static void __init offb_init_fb(const char *name, const char *full_name,
395 488
396 info->fbops = &offb_ops; 489 info->fbops = &offb_ops;
397 info->screen_base = ioremap(address, fix->smem_len); 490 info->screen_base = ioremap(address, fix->smem_len);
398 info->par = par;
399 info->pseudo_palette = (void *) (info + 1); 491 info->pseudo_palette = (void *) (info + 1);
400 info->flags = FBINFO_DEFAULT | foreign_endian; 492 info->flags = FBINFO_DEFAULT | foreign_endian;
401 493
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
index 4d8ad9cd0e19..9dfcf39d3367 100644
--- a/drivers/video/omap/blizzard.c
+++ b/drivers/video/omap/blizzard.c
@@ -26,9 +26,9 @@
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28 28
29#include <asm/arch/dma.h> 29#include <mach/dma.h>
30#include <asm/arch/omapfb.h> 30#include <mach/omapfb.h>
31#include <asm/arch/blizzard.h> 31#include <mach/blizzard.h>
32 32
33#include "dispc.h" 33#include "dispc.h"
34 34
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index ab32ceb06178..dfb72f5e4c96 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -20,13 +20,14 @@
20 */ 20 */
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
23#include <linux/mm.h>
23#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
25#include <linux/io.h> 26#include <linux/io.h>
26 27
27#include <asm/arch/sram.h> 28#include <mach/sram.h>
28#include <asm/arch/omapfb.h> 29#include <mach/omapfb.h>
29#include <asm/arch/board.h> 30#include <mach/board.h>
30 31
31#include "dispc.h" 32#include "dispc.h"
32 33
@@ -155,7 +156,7 @@ struct resmap {
155}; 156};
156 157
157static struct { 158static struct {
158 u32 base; 159 void __iomem *base;
159 160
160 struct omapfb_mem_desc mem_desc; 161 struct omapfb_mem_desc mem_desc;
161 struct resmap *res_map[DISPC_MEMTYPE_NUM]; 162 struct resmap *res_map[DISPC_MEMTYPE_NUM];
@@ -211,9 +212,9 @@ static void enable_rfbi_mode(int enable)
211 dispc_write_reg(DISPC_CONTROL, l); 212 dispc_write_reg(DISPC_CONTROL, l);
212 213
213 /* Set bypass mode in RFBI module */ 214 /* Set bypass mode in RFBI module */
214 l = __raw_readl(io_p2v(RFBI_CONTROL)); 215 l = __raw_readl(IO_ADDRESS(RFBI_CONTROL));
215 l |= enable ? 0 : (1 << 1); 216 l |= enable ? 0 : (1 << 1);
216 __raw_writel(l, io_p2v(RFBI_CONTROL)); 217 __raw_writel(l, IO_ADDRESS(RFBI_CONTROL));
217} 218}
218 219
219static void set_lcd_data_lines(int data_lines) 220static void set_lcd_data_lines(int data_lines)
@@ -1348,14 +1349,19 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1348 1349
1349 memset(&dispc, 0, sizeof(dispc)); 1350 memset(&dispc, 0, sizeof(dispc));
1350 1351
1351 dispc.base = io_p2v(DISPC_BASE); 1352 dispc.base = ioremap(DISPC_BASE, SZ_1K);
1353 if (!dispc.base) {
1354 dev_err(fbdev->dev, "can't ioremap DISPC\n");
1355 return -ENOMEM;
1356 }
1357
1352 dispc.fbdev = fbdev; 1358 dispc.fbdev = fbdev;
1353 dispc.ext_mode = ext_mode; 1359 dispc.ext_mode = ext_mode;
1354 1360
1355 init_completion(&dispc.frame_done); 1361 init_completion(&dispc.frame_done);
1356 1362
1357 if ((r = get_dss_clocks()) < 0) 1363 if ((r = get_dss_clocks()) < 0)
1358 return r; 1364 goto fail0;
1359 1365
1360 enable_interface_clocks(1); 1366 enable_interface_clocks(1);
1361 enable_lcd_clocks(1); 1367 enable_lcd_clocks(1);
@@ -1413,7 +1419,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1413 } 1419 }
1414 1420
1415 /* L3 firewall setting: enable access to OCM RAM */ 1421 /* L3 firewall setting: enable access to OCM RAM */
1416 __raw_writel(0x402000b0, io_p2v(0x680050a0)); 1422 __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
1417 1423
1418 if ((r = alloc_palette_ram()) < 0) 1424 if ((r = alloc_palette_ram()) < 0)
1419 goto fail2; 1425 goto fail2;
@@ -1463,7 +1469,8 @@ fail1:
1463 enable_lcd_clocks(0); 1469 enable_lcd_clocks(0);
1464 enable_interface_clocks(0); 1470 enable_interface_clocks(0);
1465 put_dss_clocks(); 1471 put_dss_clocks();
1466 1472fail0:
1473 iounmap(dispc.base);
1467 return r; 1474 return r;
1468} 1475}
1469 1476
@@ -1480,6 +1487,7 @@ static void omap_dispc_cleanup(void)
1480 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); 1487 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
1481 enable_interface_clocks(0); 1488 enable_interface_clocks(0);
1482 put_dss_clocks(); 1489 put_dss_clocks();
1490 iounmap(dispc.base);
1483} 1491}
1484 1492
1485const struct lcd_ctrl omap2_int_ctrl = { 1493const struct lcd_ctrl omap2_int_ctrl = {
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
index eb1512b56ce8..ef720a78f6d5 100644
--- a/drivers/video/omap/dispc.h
+++ b/drivers/video/omap/dispc.h
@@ -40,4 +40,6 @@ extern void omap_dispc_enable_digit_out(int enable);
40extern int omap_dispc_request_irq(void (*callback)(void *data), void *data); 40extern int omap_dispc_request_irq(void (*callback)(void *data), void *data);
41extern void omap_dispc_free_irq(void); 41extern void omap_dispc_free_irq(void);
42 42
43extern const struct lcd_ctrl omap2_int_ctrl;
44
43#endif 45#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 1e642b7a20fe..f24df0b54e1c 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -26,9 +26,9 @@
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28 28
29#include <asm/arch/dma.h> 29#include <mach/dma.h>
30#include <asm/arch/omapfb.h> 30#include <mach/omapfb.h>
31#include <asm/arch/hwa742.h> 31#include <mach/hwa742.h>
32 32
33#define HWA742_REV_CODE_REG 0x0 33#define HWA742_REV_CODE_REG 0x0
34#define HWA742_CONFIG_REG 0x2 34#define HWA742_CONFIG_REG 0x2
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 31e978349a80..2486237ebba5 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -23,8 +23,8 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/i2c/tps65010.h> 24#include <linux/i2c/tps65010.h>
25 25
26#include <asm/arch/gpio.h> 26#include <mach/gpio.h>
27#include <asm/arch/omapfb.h> 27#include <mach/omapfb.h>
28 28
29#define MODULE_NAME "omapfb-lcd_h3" 29#define MODULE_NAME "omapfb-lcd_h3"
30 30
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c
index fd6f0eb16de1..6ff56430341b 100644
--- a/drivers/video/omap/lcd_h4.c
+++ b/drivers/video/omap/lcd_h4.c
@@ -22,7 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#include <asm/arch/omapfb.h> 25#include <mach/omapfb.h>
26 26
27static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) 27static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
28{ 28{
@@ -47,7 +47,7 @@ static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
47 return 0; 47 return 0;
48} 48}
49 49
50struct lcd_panel h4_panel = { 50static struct lcd_panel h4_panel = {
51 .name = "h4", 51 .name = "h4",
52 .config = OMAP_LCDC_PANEL_TFT, 52 .config = OMAP_LCDC_PANEL_TFT,
53 53
@@ -91,7 +91,7 @@ static int h4_panel_resume(struct platform_device *pdev)
91 return 0; 91 return 0;
92} 92}
93 93
94struct platform_driver h4_panel_driver = { 94static struct platform_driver h4_panel_driver = {
95 .probe = h4_panel_probe, 95 .probe = h4_panel_probe,
96 .remove = h4_panel_remove, 96 .remove = h4_panel_remove,
97 .suspend = h4_panel_suspend, 97 .suspend = h4_panel_suspend,
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index 551f385861d1..6953ed4b5820 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -23,8 +23,8 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <asm/arch/fpga.h> 26#include <mach/fpga.h>
27#include <asm/arch/omapfb.h> 27#include <mach/omapfb.h>
28 28
29static int innovator1510_panel_init(struct lcd_panel *panel, 29static int innovator1510_panel_init(struct lcd_panel *panel,
30 struct omapfb_device *fbdev) 30 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 5ef119c813e0..4c4f7ee6d733 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -22,8 +22,8 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#include <asm/arch/gpio.h> 25#include <mach/gpio.h>
26#include <asm/arch/omapfb.h> 26#include <mach/omapfb.h>
27 27
28#define MODULE_NAME "omapfb-lcd_h3" 28#define MODULE_NAME "omapfb-lcd_h3"
29 29
@@ -32,43 +32,43 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
32{ 32{
33 int r = 0; 33 int r = 0;
34 34
35 if (omap_request_gpio(14)) { 35 if (gpio_request(14, "lcd_en0")) {
36 pr_err(MODULE_NAME ": can't request GPIO 14\n"); 36 pr_err(MODULE_NAME ": can't request GPIO 14\n");
37 r = -1; 37 r = -1;
38 goto exit; 38 goto exit;
39 } 39 }
40 if (omap_request_gpio(15)) { 40 if (gpio_request(15, "lcd_en1")) {
41 pr_err(MODULE_NAME ": can't request GPIO 15\n"); 41 pr_err(MODULE_NAME ": can't request GPIO 15\n");
42 omap_free_gpio(14); 42 gpio_free(14);
43 r = -1; 43 r = -1;
44 goto exit; 44 goto exit;
45 } 45 }
46 /* configure GPIO(14, 15) as outputs */ 46 /* configure GPIO(14, 15) as outputs */
47 omap_set_gpio_direction(14, 0); 47 gpio_direction_output(14, 0);
48 omap_set_gpio_direction(15, 0); 48 gpio_direction_output(15, 0);
49exit: 49exit:
50 return r; 50 return r;
51} 51}
52 52
53static void innovator1610_panel_cleanup(struct lcd_panel *panel) 53static void innovator1610_panel_cleanup(struct lcd_panel *panel)
54{ 54{
55 omap_free_gpio(15); 55 gpio_free(15);
56 omap_free_gpio(14); 56 gpio_free(14);
57} 57}
58 58
59static int innovator1610_panel_enable(struct lcd_panel *panel) 59static int innovator1610_panel_enable(struct lcd_panel *panel)
60{ 60{
61 /* set GPIO14 and GPIO15 high */ 61 /* set GPIO14 and GPIO15 high */
62 omap_set_gpio_dataout(14, 1); 62 gpio_set_value(14, 1);
63 omap_set_gpio_dataout(15, 1); 63 gpio_set_value(15, 1);
64 return 0; 64 return 0;
65} 65}
66 66
67static void innovator1610_panel_disable(struct lcd_panel *panel) 67static void innovator1610_panel_disable(struct lcd_panel *panel)
68{ 68{
69 /* set GPIO13, GPIO14 and GPIO15 low */ 69 /* set GPIO13, GPIO14 and GPIO15 low */
70 omap_set_gpio_dataout(14, 0); 70 gpio_set_value(14, 0);
71 omap_set_gpio_dataout(15, 0); 71 gpio_set_value(15, 0);
72} 72}
73 73
74static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel) 74static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index a38038840fd6..379c96d36da5 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -23,12 +23,13 @@
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25 25
26#include <asm/arch/gpio.h> 26#include <mach/gpio.h>
27#include <asm/arch/mux.h> 27#include <mach/mux.h>
28#include <asm/arch/omapfb.h> 28#include <mach/omapfb.h>
29 29
30static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) 30static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
31{ 31{
32 /* gpio2 was allocated in board init */
32 return 0; 33 return 0;
33} 34}
34 35
@@ -47,11 +48,8 @@ static int osk_panel_enable(struct lcd_panel *panel)
47 /* Set PWL level */ 48 /* Set PWL level */
48 omap_writeb(0xFF, OMAP_PWL_ENABLE); 49 omap_writeb(0xFF, OMAP_PWL_ENABLE);
49 50
50 /* configure GPIO2 as output */ 51 /* set GPIO2 high (lcd power enabled) */
51 omap_set_gpio_direction(2, 0); 52 gpio_set_value(2, 1);
52
53 /* set GPIO2 high */
54 omap_set_gpio_dataout(2, 1);
55 53
56 return 0; 54 return 0;
57} 55}
@@ -65,7 +63,7 @@ static void osk_panel_disable(struct lcd_panel *panel)
65 omap_writeb(0x00, OMAP_PWL_CLK_ENABLE); 63 omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
66 64
67 /* set GPIO2 low */ 65 /* set GPIO2 low */
68 omap_set_gpio_dataout(2, 0); 66 gpio_set_value(2, 0);
69} 67}
70 68
71static unsigned long osk_panel_get_caps(struct lcd_panel *panel) 69static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 52bdfdac42c9..218317366e6e 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -23,8 +23,8 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <asm/arch/fpga.h> 26#include <mach/fpga.h>
27#include <asm/arch/omapfb.h> 27#include <mach/omapfb.h>
28 28
29static int palmte_panel_init(struct lcd_panel *panel, 29static int palmte_panel_init(struct lcd_panel *panel,
30 struct omapfb_device *fbdev) 30 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
index 4bb349f54356..57b0f6cf6a5a 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -29,8 +29,8 @@ GPIO13 - screen blanking
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/io.h> 30#include <linux/io.h>
31 31
32#include <asm/arch/gpio.h> 32#include <mach/gpio.h>
33#include <asm/arch/omapfb.h> 33#include <mach/omapfb.h>
34 34
35static int palmtt_panel_init(struct lcd_panel *panel, 35static int palmtt_panel_init(struct lcd_panel *panel,
36 struct omapfb_device *fbdev) 36 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
index ea6170ddff35..d33d78b11723 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -24,7 +24,7 @@
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/io.h> 25#include <linux/io.h>
26 26
27#include <asm/arch/omapfb.h> 27#include <mach/omapfb.h>
28 28
29static int palmz71_panel_init(struct lcd_panel *panel, 29static int palmz71_panel_init(struct lcd_panel *panel,
30 struct omapfb_device *fbdev) 30 struct omapfb_device *fbdev)
diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c
index c4f306a4e5c9..e55de201b8ff 100644
--- a/drivers/video/omap/lcd_sx1.c
+++ b/drivers/video/omap/lcd_sx1.c
@@ -23,10 +23,10 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <asm/arch/gpio.h> 26#include <mach/gpio.h>
27#include <asm/arch/omapfb.h> 27#include <mach/omapfb.h>
28#include <asm/arch/mcbsp.h> 28#include <mach/mcbsp.h>
29#include <asm/arch/mux.h> 29#include <mach/mux.h>
30 30
31/* 31/*
32 * OMAP310 GPIO registers 32 * OMAP310 GPIO registers
@@ -81,21 +81,21 @@ static void epson_sendbyte(int flag, unsigned char byte)
81 int i, shifter = 0x80; 81 int i, shifter = 0x80;
82 82
83 if (!flag) 83 if (!flag)
84 omap_set_gpio_dataout(_A_LCD_SSC_A0, 0); 84 gpio_set_value(_A_LCD_SSC_A0, 0);
85 mdelay(2); 85 mdelay(2);
86 omap_set_gpio_dataout(A_LCD_SSC_RD, 1); 86 gpio_set_value(A_LCD_SSC_RD, 1);
87 87
88 omap_set_gpio_dataout(A_LCD_SSC_SD, flag); 88 gpio_set_value(A_LCD_SSC_SD, flag);
89 89
90 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); 90 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
91 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); 91 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
92 for (i = 0; i < 8; i++) { 92 for (i = 0; i < 8; i++) {
93 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); 93 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
94 omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte); 94 gpio_set_value(A_LCD_SSC_SD, shifter & byte);
95 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); 95 OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
96 shifter >>= 1; 96 shifter >>= 1;
97 } 97 }
98 omap_set_gpio_dataout(_A_LCD_SSC_A0, 1); 98 gpio_set_value(_A_LCD_SSC_A0, 1);
99} 99}
100 100
101static void init_system(void) 101static void init_system(void)
@@ -107,25 +107,18 @@ static void init_system(void)
107static void setup_GPIO(void) 107static void setup_GPIO(void)
108{ 108{
109 /* new wave */ 109 /* new wave */
110 omap_request_gpio(A_LCD_SSC_RD); 110 gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd");
111 omap_request_gpio(A_LCD_SSC_SD); 111 gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd");
112 omap_request_gpio(_A_LCD_RESET); 112 gpio_request(_A_LCD_RESET, "lcd_reset");
113 omap_request_gpio(_A_LCD_SSC_CS); 113 gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs");
114 omap_request_gpio(_A_LCD_SSC_A0); 114 gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0");
115 115
116 /* set all GPIOs to output */ 116 /* set GPIOs to output, with initial data */
117 omap_set_gpio_direction(A_LCD_SSC_RD, 0); 117 gpio_direction_output(A_LCD_SSC_RD, 1);
118 omap_set_gpio_direction(A_LCD_SSC_SD, 0); 118 gpio_direction_output(A_LCD_SSC_SD, 0);
119 omap_set_gpio_direction(_A_LCD_RESET, 0); 119 gpio_direction_output(_A_LCD_RESET, 0);
120 omap_set_gpio_direction(_A_LCD_SSC_CS, 0); 120 gpio_direction_output(_A_LCD_SSC_CS, 1);
121 omap_set_gpio_direction(_A_LCD_SSC_A0, 0); 121 gpio_direction_output(_A_LCD_SSC_A0, 1);
122
123 /* set GPIO data */
124 omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
125 omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
126 omap_set_gpio_dataout(_A_LCD_RESET, 0);
127 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
128 omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
129} 122}
130 123
131static void display_init(void) 124static void display_init(void)
@@ -139,61 +132,61 @@ static void display_init(void)
139 mdelay(2); 132 mdelay(2);
140 133
141 /* reset LCD */ 134 /* reset LCD */
142 omap_set_gpio_dataout(A_LCD_SSC_SD, 1); 135 gpio_set_value(A_LCD_SSC_SD, 1);
143 epson_sendbyte(0, 0x25); 136 epson_sendbyte(0, 0x25);
144 137
145 omap_set_gpio_dataout(_A_LCD_RESET, 0); 138 gpio_set_value(_A_LCD_RESET, 0);
146 mdelay(10); 139 mdelay(10);
147 omap_set_gpio_dataout(_A_LCD_RESET, 1); 140 gpio_set_value(_A_LCD_RESET, 1);
148 141
149 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 142 gpio_set_value(_A_LCD_SSC_CS, 1);
150 mdelay(2); 143 mdelay(2);
151 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 144 gpio_set_value(_A_LCD_SSC_CS, 0);
152 145
153 /* init LCD, phase 1 */ 146 /* init LCD, phase 1 */
154 epson_sendbyte(0, 0xCA); 147 epson_sendbyte(0, 0xCA);
155 for (i = 0; i < 10; i++) 148 for (i = 0; i < 10; i++)
156 epson_sendbyte(1, INIT_1[i]); 149 epson_sendbyte(1, INIT_1[i]);
157 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 150 gpio_set_value(_A_LCD_SSC_CS, 1);
158 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 151 gpio_set_value(_A_LCD_SSC_CS, 0);
159 152
160 /* init LCD phase 2 */ 153 /* init LCD phase 2 */
161 epson_sendbyte(0, 0xCB); 154 epson_sendbyte(0, 0xCB);
162 for (i = 0; i < 125; i++) 155 for (i = 0; i < 125; i++)
163 epson_sendbyte(1, INIT_2[i]); 156 epson_sendbyte(1, INIT_2[i]);
164 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 157 gpio_set_value(_A_LCD_SSC_CS, 1);
165 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 158 gpio_set_value(_A_LCD_SSC_CS, 0);
166 159
167 /* init LCD phase 2a */ 160 /* init LCD phase 2a */
168 epson_sendbyte(0, 0xCC); 161 epson_sendbyte(0, 0xCC);
169 for (i = 0; i < 14; i++) 162 for (i = 0; i < 14; i++)
170 epson_sendbyte(1, INIT_3[i]); 163 epson_sendbyte(1, INIT_3[i]);
171 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 164 gpio_set_value(_A_LCD_SSC_CS, 1);
172 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 165 gpio_set_value(_A_LCD_SSC_CS, 0);
173 166
174 /* init LCD phase 3 */ 167 /* init LCD phase 3 */
175 epson_sendbyte(0, 0xBC); 168 epson_sendbyte(0, 0xBC);
176 epson_sendbyte(1, 0x08); 169 epson_sendbyte(1, 0x08);
177 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 170 gpio_set_value(_A_LCD_SSC_CS, 1);
178 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 171 gpio_set_value(_A_LCD_SSC_CS, 0);
179 172
180 /* init LCD phase 4 */ 173 /* init LCD phase 4 */
181 epson_sendbyte(0, 0x07); 174 epson_sendbyte(0, 0x07);
182 epson_sendbyte(1, 0x05); 175 epson_sendbyte(1, 0x05);
183 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 176 gpio_set_value(_A_LCD_SSC_CS, 1);
184 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 177 gpio_set_value(_A_LCD_SSC_CS, 0);
185 178
186 /* init LCD phase 5 */ 179 /* init LCD phase 5 */
187 epson_sendbyte(0, 0x94); 180 epson_sendbyte(0, 0x94);
188 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 181 gpio_set_value(_A_LCD_SSC_CS, 1);
189 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 182 gpio_set_value(_A_LCD_SSC_CS, 0);
190 183
191 /* init LCD phase 6 */ 184 /* init LCD phase 6 */
192 epson_sendbyte(0, 0xC6); 185 epson_sendbyte(0, 0xC6);
193 epson_sendbyte(1, 0x80); 186 epson_sendbyte(1, 0x80);
194 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 187 gpio_set_value(_A_LCD_SSC_CS, 1);
195 mdelay(100); /* used to be 1000 */ 188 mdelay(100); /* used to be 1000 */
196 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 189 gpio_set_value(_A_LCD_SSC_CS, 0);
197 190
198 /* init LCD phase 7 */ 191 /* init LCD phase 7 */
199 epson_sendbyte(0, 0x16); 192 epson_sendbyte(0, 0x16);
@@ -201,8 +194,8 @@ static void display_init(void)
201 epson_sendbyte(1, 0x00); 194 epson_sendbyte(1, 0x00);
202 epson_sendbyte(1, 0xB1); 195 epson_sendbyte(1, 0xB1);
203 epson_sendbyte(1, 0x00); 196 epson_sendbyte(1, 0x00);
204 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 197 gpio_set_value(_A_LCD_SSC_CS, 1);
205 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 198 gpio_set_value(_A_LCD_SSC_CS, 0);
206 199
207 /* init LCD phase 8 */ 200 /* init LCD phase 8 */
208 epson_sendbyte(0, 0x76); 201 epson_sendbyte(0, 0x76);
@@ -210,12 +203,12 @@ static void display_init(void)
210 epson_sendbyte(1, 0x00); 203 epson_sendbyte(1, 0x00);
211 epson_sendbyte(1, 0xDB); 204 epson_sendbyte(1, 0xDB);
212 epson_sendbyte(1, 0x00); 205 epson_sendbyte(1, 0x00);
213 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 206 gpio_set_value(_A_LCD_SSC_CS, 1);
214 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 207 gpio_set_value(_A_LCD_SSC_CS, 0);
215 208
216 /* init LCD phase 9 */ 209 /* init LCD phase 9 */
217 epson_sendbyte(0, 0xAF); 210 epson_sendbyte(0, 0xAF);
218 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 211 gpio_set_value(_A_LCD_SSC_CS, 1);
219} 212}
220 213
221static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) 214static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
@@ -231,18 +224,18 @@ static void sx1_panel_disable(struct lcd_panel *panel)
231{ 224{
232 printk(KERN_INFO "SX1: LCD panel disable\n"); 225 printk(KERN_INFO "SX1: LCD panel disable\n");
233 sx1_setmmipower(0); 226 sx1_setmmipower(0);
234 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 227 gpio_set_value(_A_LCD_SSC_CS, 1);
235 228
236 epson_sendbyte(0, 0x25); 229 epson_sendbyte(0, 0x25);
237 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 230 gpio_set_value(_A_LCD_SSC_CS, 0);
238 231
239 epson_sendbyte(0, 0xAE); 232 epson_sendbyte(0, 0xAE);
240 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 233 gpio_set_value(_A_LCD_SSC_CS, 1);
241 mdelay(100); 234 mdelay(100);
242 omap_set_gpio_dataout(_A_LCD_SSC_CS, 0); 235 gpio_set_value(_A_LCD_SSC_CS, 0);
243 236
244 epson_sendbyte(0, 0x95); 237 epson_sendbyte(0, 0x95);
245 omap_set_gpio_dataout(_A_LCD_SSC_CS, 1); 238 gpio_set_value(_A_LCD_SSC_CS, 1);
246} 239}
247 240
248static int sx1_panel_enable(struct lcd_panel *panel) 241static int sx1_panel_enable(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index fb19ed4992db..6e2ea7518761 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -29,11 +29,13 @@
29#include <linux/vmalloc.h> 29#include <linux/vmalloc.h>
30#include <linux/clk.h> 30#include <linux/clk.h>
31 31
32#include <asm/arch/dma.h> 32#include <mach/dma.h>
33#include <asm/arch/omapfb.h> 33#include <mach/omapfb.h>
34 34
35#include <asm/mach-types.h> 35#include <asm/mach-types.h>
36 36
37#include "lcdc.h"
38
37#define MODULE_NAME "lcdc" 39#define MODULE_NAME "lcdc"
38 40
39#define OMAP_LCDC_BASE 0xfffec000 41#define OMAP_LCDC_BASE 0xfffec000
diff --git a/drivers/video/omap/lcdc.h b/drivers/video/omap/lcdc.h
index adb731e5314a..845222270db3 100644
--- a/drivers/video/omap/lcdc.h
+++ b/drivers/video/omap/lcdc.h
@@ -4,4 +4,6 @@
4int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data); 4int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
5void omap_lcdc_free_dma_callback(void); 5void omap_lcdc_free_dma_callback(void);
6 6
7extern const struct lcd_ctrl omap1_int_ctrl;
8
7#endif 9#endif
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 14d0f7a11145..5a5e407dc45f 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -25,17 +25,20 @@
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */ 26 */
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/mm.h>
28#include <linux/uaccess.h> 29#include <linux/uaccess.h>
29 30
30#include <asm/mach-types.h> 31#include <mach/dma.h>
31#include <asm/arch/dma.h> 32#include <mach/omapfb.h>
32#include <asm/arch/omapfb.h> 33
34#include "lcdc.h"
35#include "dispc.h"
33 36
34#define MODULE_NAME "omapfb" 37#define MODULE_NAME "omapfb"
35 38
36static unsigned int def_accel; 39static unsigned int def_accel;
37static unsigned long def_vram[OMAPFB_PLANE_NUM]; 40static unsigned long def_vram[OMAPFB_PLANE_NUM];
38static int def_vram_cnt; 41static unsigned int def_vram_cnt;
39static unsigned long def_vxres; 42static unsigned long def_vxres;
40static unsigned long def_vyres; 43static unsigned long def_vyres;
41static unsigned int def_rotate; 44static unsigned int def_rotate;
@@ -84,12 +87,10 @@ static struct caps_table_struct color_caps[] = {
84 * LCD panel 87 * LCD panel
85 * --------------------------------------------------------------------------- 88 * ---------------------------------------------------------------------------
86 */ 89 */
87extern struct lcd_ctrl omap1_int_ctrl;
88extern struct lcd_ctrl omap2_int_ctrl;
89extern struct lcd_ctrl hwa742_ctrl; 90extern struct lcd_ctrl hwa742_ctrl;
90extern struct lcd_ctrl blizzard_ctrl; 91extern struct lcd_ctrl blizzard_ctrl;
91 92
92static struct lcd_ctrl *ctrls[] = { 93static const struct lcd_ctrl *ctrls[] = {
93#ifdef CONFIG_ARCH_OMAP1 94#ifdef CONFIG_ARCH_OMAP1
94 &omap1_int_ctrl, 95 &omap1_int_ctrl,
95#else 96#else
@@ -740,7 +741,7 @@ static int omapfb_update_win(struct fb_info *fbi,
740 int ret; 741 int ret;
741 742
742 omapfb_rqueue_lock(plane->fbdev); 743 omapfb_rqueue_lock(plane->fbdev);
743 ret = omapfb_update_window_async(fbi, win, NULL, 0); 744 ret = omapfb_update_window_async(fbi, win, NULL, NULL);
744 omapfb_rqueue_unlock(plane->fbdev); 745 omapfb_rqueue_unlock(plane->fbdev);
745 746
746 return ret; 747 return ret;
@@ -768,7 +769,7 @@ static int omapfb_update_full_screen(struct fb_info *fbi)
768 win.format = 0; 769 win.format = 0;
769 770
770 omapfb_rqueue_lock(fbdev); 771 omapfb_rqueue_lock(fbdev);
771 r = fbdev->ctrl->update_window(fbi, &win, NULL, 0); 772 r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
772 omapfb_rqueue_unlock(fbdev); 773 omapfb_rqueue_unlock(fbdev);
773 774
774 return r; 775 return r;
@@ -1047,7 +1048,7 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
1047 win.height = 2; 1048 win.height = 2;
1048 win.out_width = 2; 1049 win.out_width = 2;
1049 win.out_height = 2; 1050 win.out_height = 2;
1050 fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0); 1051 fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
1051 } 1052 }
1052 omapfb_rqueue_unlock(fbdev); 1053 omapfb_rqueue_unlock(fbdev);
1053} 1054}
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
index 789cfd23c36b..a13c8dcad2a8 100644
--- a/drivers/video/omap/rfbi.c
+++ b/drivers/video/omap/rfbi.c
@@ -27,7 +27,7 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/io.h> 28#include <linux/io.h>
29 29
30#include <asm/arch/omapfb.h> 30#include <mach/omapfb.h>
31 31
32#include "dispc.h" 32#include "dispc.h"
33 33
@@ -59,7 +59,7 @@
59#define DISPC_CONTROL 0x0040 59#define DISPC_CONTROL 0x0040
60 60
61static struct { 61static struct {
62 u32 base; 62 void __iomem *base;
63 void (*lcdc_callback)(void *data); 63 void (*lcdc_callback)(void *data);
64 void *lcdc_callback_data; 64 void *lcdc_callback_data;
65 unsigned long l4_khz; 65 unsigned long l4_khz;
@@ -518,7 +518,11 @@ static int rfbi_init(struct omapfb_device *fbdev)
518 int r; 518 int r;
519 519
520 rfbi.fbdev = fbdev; 520 rfbi.fbdev = fbdev;
521 rfbi.base = io_p2v(RFBI_BASE); 521 rfbi.base = ioremap(RFBI_BASE, SZ_1K);
522 if (!rfbi.base) {
523 dev_err(fbdev->dev, "can't ioremap RFBI\n");
524 return -ENOMEM;
525 }
522 526
523 if ((r = rfbi_get_clocks()) < 0) 527 if ((r = rfbi_get_clocks()) < 0)
524 return r; 528 return r;
@@ -566,6 +570,7 @@ static void rfbi_cleanup(void)
566{ 570{
567 omap_dispc_free_irq(); 571 omap_dispc_free_irq();
568 rfbi_put_clocks(); 572 rfbi_put_clocks();
573 iounmap(rfbi.base);
569} 574}
570 575
571const struct lcd_ctrl_extif omap2_ext_if = { 576const struct lcd_ctrl_extif omap2_ext_if = {
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index 81dbcf53cf0e..a76946220249 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -24,8 +24,8 @@
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/io.h> 25#include <linux/io.h>
26 26
27#include <asm/arch/dma.h> 27#include <mach/dma.h>
28#include <asm/arch/omapfb.h> 28#include <mach/omapfb.h>
29 29
30#include "lcdc.h" 30#include "lcdc.h"
31 31
@@ -574,7 +574,12 @@ static int sossi_init(struct omapfb_device *fbdev)
574 struct clk *dpll1out_ck; 574 struct clk *dpll1out_ck;
575 int r; 575 int r;
576 576
577 sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE); 577 sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K);
578 if (!sossi.base) {
579 dev_err(fbdev->dev, "can't ioremap SoSSI\n");
580 return -ENOMEM;
581 }
582
578 sossi.fbdev = fbdev; 583 sossi.fbdev = fbdev;
579 spin_lock_init(&sossi.lock); 584 spin_lock_init(&sossi.lock);
580 585
@@ -646,7 +651,7 @@ static int sossi_init(struct omapfb_device *fbdev)
646 sossi_write_reg(SOSSI_INIT1_REG, l); 651 sossi_write_reg(SOSSI_INIT1_REG, l);
647 652
648 if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq, 653 if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
649 IRQT_FALLING, 654 IRQ_TYPE_EDGE_FALLING,
650 "sossi_match", sossi.fbdev->dev)) < 0) { 655 "sossi_match", sossi.fbdev->dev)) < 0) {
651 dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n"); 656 dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
652 goto err; 657 goto err;
@@ -665,6 +670,7 @@ static void sossi_cleanup(void)
665{ 670{
666 omap_lcdc_free_dma_callback(); 671 omap_lcdc_free_dma_callback();
667 clk_put(sossi.fck); 672 clk_put(sossi.fck);
673 iounmap(sossi.base);
668} 674}
669 675
670struct lcd_ctrl_extif omap1_ext_if = { 676struct lcd_ctrl_extif omap1_ext_if = {
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 9e903454ffc1..7000f2cd5854 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -349,7 +349,7 @@ static int __devexit p9100_remove(struct of_device *op)
349 return 0; 349 return 0;
350} 350}
351 351
352static struct of_device_id p9100_match[] = { 352static const struct of_device_id p9100_match[] = {
353 { 353 {
354 .name = "p9100", 354 .name = "p9100",
355 }, 355 },
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 3f1ca2adda3d..c6dd924976a4 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -1746,6 +1746,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev)
1746 release_mem_region(fix->mmio_start, fix->mmio_len); 1746 release_mem_region(fix->mmio_start, fix->mmio_len);
1747 1747
1748 pci_set_drvdata(pdev, NULL); 1748 pci_set_drvdata(pdev, NULL);
1749 fb_dealloc_cmap(&info->cmap);
1749 kfree(info->pixmap.addr); 1750 kfree(info->pixmap.addr);
1750 kfree(info); 1751 kfree(info);
1751} 1752}
diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h
index d80a614d89ed..1234d4375d92 100644
--- a/drivers/video/pnx4008/dum.h
+++ b/drivers/video/pnx4008/dum.h
@@ -12,7 +12,7 @@
12#ifndef __PNX008_DUM_H__ 12#ifndef __PNX008_DUM_H__
13#define __PNX008_DUM_H__ 13#define __PNX008_DUM_H__
14 14
15#include <asm/arch/platform.h> 15#include <mach/platform.h>
16 16
17#define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE) 17#define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE)
18#define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE) 18#define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE)
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
index d23bf0d659b6..2aa09bce3944 100644
--- a/drivers/video/pnx4008/sdum.c
+++ b/drivers/video/pnx4008/sdum.c
@@ -30,7 +30,7 @@
30#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
31#include <linux/clk.h> 31#include <linux/clk.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33#include <asm/arch/gpio.h> 33#include <mach/gpio.h>
34 34
35#include "sdum.h" 35#include "sdum.h"
36#include "fbcommon.h" 36#include "fbcommon.h"
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index dc3af1c78c56..4b5d80771904 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1297,6 +1297,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
1297 1297
1298static struct ps3_system_bus_driver ps3fb_driver = { 1298static struct ps3_system_bus_driver ps3fb_driver = {
1299 .match_id = PS3_MATCH_ID_GRAPHICS, 1299 .match_id = PS3_MATCH_ID_GRAPHICS,
1300 .match_sub_id = PS3_MATCH_SUB_ID_FB,
1300 .core.name = DEVICE_NAME, 1301 .core.name = DEVICE_NAME,
1301 .core.owner = THIS_MODULE, 1302 .core.owner = THIS_MODULE,
1302 .probe = ps3fb_probe, 1303 .probe = ps3fb_probe,
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 8c863a7f654b..0a0fd48a8566 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -58,18 +58,18 @@
58 58
59#ifdef CONFIG_SH_DREAMCAST 59#ifdef CONFIG_SH_DREAMCAST
60#include <asm/machvec.h> 60#include <asm/machvec.h>
61#include <asm/mach/sysasic.h> 61#include <mach-dreamcast/mach/sysasic.h>
62#endif 62#endif
63 63
64#ifdef CONFIG_SH_DMA 64#ifdef CONFIG_SH_DMA
65#include <linux/pagemap.h> 65#include <linux/pagemap.h>
66#include <asm/mach/dma.h> 66#include <mach/dma.h>
67#include <asm/dma.h> 67#include <asm/dma.h>
68#endif 68#endif
69 69
70#ifdef CONFIG_SH_STORE_QUEUES 70#ifdef CONFIG_SH_STORE_QUEUES
71#include <linux/uaccess.h> 71#include <linux/uaccess.h>
72#include <asm/cpu/sq.h> 72#include <cpu/sq.h>
73#endif 73#endif
74 74
75#ifndef PCI_DEVICE_ID_NEC_NEON250 75#ifndef PCI_DEVICE_ID_NEC_NEON250
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index d0746261c957..97204497d9f7 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -30,6 +30,7 @@
30#include <linux/string.h> 30#include <linux/string.h>
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/mm.h>
33#include <linux/fb.h> 34#include <linux/fb.h>
34#include <linux/delay.h> 35#include <linux/delay.h>
35#include <linux/init.h> 36#include <linux/init.h>
@@ -40,17 +41,18 @@
40#include <linux/clk.h> 41#include <linux/clk.h>
41#include <linux/err.h> 42#include <linux/err.h>
42#include <linux/completion.h> 43#include <linux/completion.h>
44#include <linux/mutex.h>
43#include <linux/kthread.h> 45#include <linux/kthread.h>
44#include <linux/freezer.h> 46#include <linux/freezer.h>
45 47
46#include <asm/hardware.h> 48#include <mach/hardware.h>
47#include <asm/io.h> 49#include <asm/io.h>
48#include <asm/irq.h> 50#include <asm/irq.h>
49#include <asm/div64.h> 51#include <asm/div64.h>
50#include <asm/arch/pxa-regs.h> 52#include <mach/pxa-regs.h>
51#include <asm/arch/pxa2xx-gpio.h> 53#include <mach/pxa2xx-gpio.h>
52#include <asm/arch/bitfield.h> 54#include <mach/bitfield.h>
53#include <asm/arch/pxafb.h> 55#include <mach/pxafb.h>
54 56
55/* 57/*
56 * Complain if VAR is out of range. 58 * Complain if VAR is out of range.
@@ -227,6 +229,22 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
227 case 4: ret = LCCR3_4BPP; break; 229 case 4: ret = LCCR3_4BPP; break;
228 case 8: ret = LCCR3_8BPP; break; 230 case 8: ret = LCCR3_8BPP; break;
229 case 16: ret = LCCR3_16BPP; break; 231 case 16: ret = LCCR3_16BPP; break;
232 case 24:
233 switch (var->red.length + var->green.length +
234 var->blue.length + var->transp.length) {
235 case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break;
236 case 19: ret = LCCR3_19BPP_P; break;
237 }
238 break;
239 case 32:
240 switch (var->red.length + var->green.length +
241 var->blue.length + var->transp.length) {
242 case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break;
243 case 19: ret = LCCR3_19BPP; break;
244 case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break;
245 case 25: ret = LCCR3_25BPP; break;
246 }
247 break;
230 } 248 }
231 return ret; 249 return ret;
232} 250}
@@ -345,6 +363,41 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
345 var->green.offset = 5; var->green.length = 6; 363 var->green.offset = 5; var->green.length = 6;
346 var->blue.offset = 0; var->blue.length = 5; 364 var->blue.offset = 0; var->blue.length = 5;
347 var->transp.offset = var->transp.length = 0; 365 var->transp.offset = var->transp.length = 0;
366 } else if (var->bits_per_pixel > 16) {
367 struct pxafb_mode_info *mode;
368
369 mode = pxafb_getmode(inf, var);
370 if (!mode)
371 return -EINVAL;
372
373 switch (mode->depth) {
374 case 18: /* RGB666 */
375 var->transp.offset = var->transp.length = 0;
376 var->red.offset = 12; var->red.length = 6;
377 var->green.offset = 6; var->green.length = 6;
378 var->blue.offset = 0; var->blue.length = 6;
379 break;
380 case 19: /* RGBT666 */
381 var->transp.offset = 18; var->transp.length = 1;
382 var->red.offset = 12; var->red.length = 6;
383 var->green.offset = 6; var->green.length = 6;
384 var->blue.offset = 0; var->blue.length = 6;
385 break;
386 case 24: /* RGB888 */
387 var->transp.offset = var->transp.length = 0;
388 var->red.offset = 16; var->red.length = 8;
389 var->green.offset = 8; var->green.length = 8;
390 var->blue.offset = 0; var->blue.length = 8;
391 break;
392 case 25: /* RGBT888 */
393 var->transp.offset = 24; var->transp.length = 1;
394 var->red.offset = 16; var->red.length = 8;
395 var->green.offset = 8; var->green.length = 8;
396 var->blue.offset = 0; var->blue.length = 8;
397 break;
398 default:
399 return -EINVAL;
400 }
348 } else { 401 } else {
349 var->red.offset = var->green.offset = 0; 402 var->red.offset = var->green.offset = 0;
350 var->blue.offset = var->transp.offset = 0; 403 var->blue.offset = var->transp.offset = 0;
@@ -376,7 +429,7 @@ static int pxafb_set_par(struct fb_info *info)
376 struct pxafb_info *fbi = (struct pxafb_info *)info; 429 struct pxafb_info *fbi = (struct pxafb_info *)info;
377 struct fb_var_screeninfo *var = &info->var; 430 struct fb_var_screeninfo *var = &info->var;
378 431
379 if (var->bits_per_pixel == 16) 432 if (var->bits_per_pixel >= 16)
380 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; 433 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
381 else if (!fbi->cmap_static) 434 else if (!fbi->cmap_static)
382 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; 435 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -391,7 +444,7 @@ static int pxafb_set_par(struct fb_info *info)
391 444
392 fbi->fb.fix.line_length = var->xres_virtual * 445 fbi->fb.fix.line_length = var->xres_virtual *
393 var->bits_per_pixel / 8; 446 var->bits_per_pixel / 8;
394 if (var->bits_per_pixel == 16) 447 if (var->bits_per_pixel >= 16)
395 fbi->palette_size = 0; 448 fbi->palette_size = 0;
396 else 449 else
397 fbi->palette_size = var->bits_per_pixel == 1 ? 450 fbi->palette_size = var->bits_per_pixel == 1 ?
@@ -404,7 +457,7 @@ static int pxafb_set_par(struct fb_info *info)
404 */ 457 */
405 pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); 458 pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
406 459
407 if (fbi->fb.var.bits_per_pixel == 16) 460 if (fbi->fb.var.bits_per_pixel >= 16)
408 fb_dealloc_cmap(&fbi->fb.cmap); 461 fb_dealloc_cmap(&fbi->fb.cmap);
409 else 462 else
410 fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0); 463 fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -831,6 +884,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
831 case 4: 884 case 4:
832 case 8: 885 case 8:
833 case 16: 886 case 16:
887 case 24:
888 case 32:
834 break; 889 break;
835 default: 890 default:
836 printk(KERN_ERR "%s: invalid bit depth %d\n", 891 printk(KERN_ERR "%s: invalid bit depth %d\n",
@@ -968,10 +1023,17 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
968 1023
969 for (gpio = 58; ldd_bits; gpio++, ldd_bits--) 1024 for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
970 pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT); 1025 pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
1026 /* 18 bit interface */
1027 if (fbi->fb.var.bits_per_pixel > 16) {
1028 pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
1029 pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
1030 }
971 pxa_gpio_mode(GPIO74_LCD_FCLK_MD); 1031 pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
972 pxa_gpio_mode(GPIO75_LCD_LCLK_MD); 1032 pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
973 pxa_gpio_mode(GPIO76_LCD_PCLK_MD); 1033 pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
974 pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD); 1034
1035 if ((lccr0 & LCCR0_PAS) == 0)
1036 pxa_gpio_mode(GPIO77_LCD_ACBIAS_MD);
975} 1037}
976 1038
977static void pxafb_enable_controller(struct pxafb_info *fbi) 1039static void pxafb_enable_controller(struct pxafb_info *fbi)
@@ -1058,7 +1120,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
1058{ 1120{
1059 u_int old_state; 1121 u_int old_state;
1060 1122
1061 down(&fbi->ctrlr_sem); 1123 mutex_lock(&fbi->ctrlr_lock);
1062 1124
1063 old_state = fbi->state; 1125 old_state = fbi->state;
1064 1126
@@ -1146,7 +1208,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
1146 } 1208 }
1147 break; 1209 break;
1148 } 1210 }
1149 up(&fbi->ctrlr_sem); 1211 mutex_unlock(&fbi->ctrlr_lock);
1150} 1212}
1151 1213
1152/* 1214/*
@@ -1276,7 +1338,7 @@ static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
1276 fbi->dma_buff_phys = fbi->map_dma; 1338 fbi->dma_buff_phys = fbi->map_dma;
1277 fbi->palette_cpu = (u16 *) fbi->dma_buff->palette; 1339 fbi->palette_cpu = (u16 *) fbi->dma_buff->palette;
1278 1340
1279 pr_debug("pxafb: palette_mem_size = 0x%08lx\n", fbi->palette_size*sizeof(u16)); 1341 pr_debug("pxafb: palette_mem_size = 0x%08x\n", fbi->palette_size*sizeof(u16));
1280 1342
1281#ifdef CONFIG_FB_PXA_SMARTPANEL 1343#ifdef CONFIG_FB_PXA_SMARTPANEL
1282 fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff; 1344 fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
@@ -1340,6 +1402,8 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi,
1340 if (lcd_conn == LCD_MONO_STN_8BPP) 1402 if (lcd_conn == LCD_MONO_STN_8BPP)
1341 fbi->lccr0 |= LCCR0_DPD; 1403 fbi->lccr0 |= LCCR0_DPD;
1342 1404
1405 fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;
1406
1343 fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff); 1407 fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
1344 fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0; 1408 fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
1345 fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0; 1409 fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL) ? LCCR3_PCP : 0;
@@ -1399,7 +1463,7 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
1399 1463
1400 init_waitqueue_head(&fbi->ctrlr_wait); 1464 init_waitqueue_head(&fbi->ctrlr_wait);
1401 INIT_WORK(&fbi->task, pxafb_task); 1465 INIT_WORK(&fbi->task, pxafb_task);
1402 init_MUTEX(&fbi->ctrlr_sem); 1466 mutex_init(&fbi->ctrlr_lock);
1403 init_completion(&fbi->disable_done); 1467 init_completion(&fbi->disable_done);
1404#ifdef CONFIG_FB_PXA_SMARTPANEL 1468#ifdef CONFIG_FB_PXA_SMARTPANEL
1405 init_completion(&fbi->command_done); 1469 init_completion(&fbi->command_done);
@@ -1613,53 +1677,63 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
1613#define pxafb_setup_options() (0) 1677#define pxafb_setup_options() (0)
1614#endif 1678#endif
1615 1679
1616static int __devinit pxafb_probe(struct platform_device *dev)
1617{
1618 struct pxafb_info *fbi;
1619 struct pxafb_mach_info *inf;
1620 struct resource *r;
1621 int irq, ret;
1622
1623 dev_dbg(&dev->dev, "pxafb_probe\n");
1624
1625 inf = dev->dev.platform_data;
1626 ret = -ENOMEM;
1627 fbi = NULL;
1628 if (!inf)
1629 goto failed;
1630
1631 ret = pxafb_parse_options(&dev->dev, g_options);
1632 if (ret < 0)
1633 goto failed;
1634
1635#ifdef DEBUG_VAR 1680#ifdef DEBUG_VAR
1636 /* Check for various illegal bit-combinations. Currently only 1681/* Check for various illegal bit-combinations. Currently only
1637 * a warning is given. */ 1682 * a warning is given. */
1683static void __devinit pxafb_check_options(struct device *dev,
1684 struct pxafb_mach_info *inf)
1685{
1686 if (inf->lcd_conn)
1687 return;
1638 1688
1639 if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK) 1689 if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
1640 dev_warn(&dev->dev, "machine LCCR0 setting contains " 1690 dev_warn(dev, "machine LCCR0 setting contains "
1641 "illegal bits: %08x\n", 1691 "illegal bits: %08x\n",
1642 inf->lccr0 & LCCR0_INVALID_CONFIG_MASK); 1692 inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
1643 if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK) 1693 if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
1644 dev_warn(&dev->dev, "machine LCCR3 setting contains " 1694 dev_warn(dev, "machine LCCR3 setting contains "
1645 "illegal bits: %08x\n", 1695 "illegal bits: %08x\n",
1646 inf->lccr3 & LCCR3_INVALID_CONFIG_MASK); 1696 inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
1647 if (inf->lccr0 & LCCR0_DPD && 1697 if (inf->lccr0 & LCCR0_DPD &&
1648 ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas || 1698 ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
1649 (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl || 1699 (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
1650 (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono)) 1700 (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
1651 dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is " 1701 dev_warn(dev, "Double Pixel Data (DPD) mode is "
1652 "only valid in passive mono" 1702 "only valid in passive mono"
1653 " single panel mode\n"); 1703 " single panel mode\n");
1654 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act && 1704 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
1655 (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual) 1705 (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
1656 dev_warn(&dev->dev, "Dual panel only valid in passive mode\n"); 1706 dev_warn(dev, "Dual panel only valid in passive mode\n");
1657 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas && 1707 if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
1658 (inf->modes->upper_margin || inf->modes->lower_margin)) 1708 (inf->modes->upper_margin || inf->modes->lower_margin))
1659 dev_warn(&dev->dev, "Upper and lower margins must be 0 in " 1709 dev_warn(dev, "Upper and lower margins must be 0 in "
1660 "passive mode\n"); 1710 "passive mode\n");
1711}
1712#else
1713#define pxafb_check_options(...) do {} while (0)
1661#endif 1714#endif
1662 1715
1716static int __devinit pxafb_probe(struct platform_device *dev)
1717{
1718 struct pxafb_info *fbi;
1719 struct pxafb_mach_info *inf;
1720 struct resource *r;
1721 int irq, ret;
1722
1723 dev_dbg(&dev->dev, "pxafb_probe\n");
1724
1725 inf = dev->dev.platform_data;
1726 ret = -ENOMEM;
1727 fbi = NULL;
1728 if (!inf)
1729 goto failed;
1730
1731 ret = pxafb_parse_options(&dev->dev, g_options);
1732 if (ret < 0)
1733 goto failed;
1734
1735 pxafb_check_options(&dev->dev, inf);
1736
1663 dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n", 1737 dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
1664 inf->modes->xres, 1738 inf->modes->xres,
1665 inf->modes->yres, 1739 inf->modes->yres,
diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
index 8238dc826429..31541b86f13d 100644
--- a/drivers/video/pxafb.h
+++ b/drivers/video/pxafb.h
@@ -106,7 +106,7 @@ struct pxafb_info {
106 106
107 volatile u_char state; 107 volatile u_char state;
108 volatile u_char task_state; 108 volatile u_char task_state;
109 struct semaphore ctrlr_sem; 109 struct mutex ctrlr_lock;
110 wait_queue_head_t ctrlr_wait; 110 wait_queue_head_t ctrlr_wait;
111 struct work_struct task; 111 struct work_struct task;
112 112
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index b829dc7c5edf..a7b01d2724b5 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -50,6 +50,11 @@
50#define dbg(fmt, args...) do { } while (0) 50#define dbg(fmt, args...) do { } while (0)
51#endif 51#endif
52 52
53static const int __devinitconst s1d13xxxfb_revisions[] = {
54 S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */
55 S1D13806_CHIP_REV, /* Rev.7 on .. */
56};
57
53/* 58/*
54 * Here we define the default struct fb_fix_screeninfo 59 * Here we define the default struct fb_fix_screeninfo
55 */ 60 */
@@ -538,6 +543,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
538 struct fb_info *info; 543 struct fb_info *info;
539 struct s1d13xxxfb_pdata *pdata = NULL; 544 struct s1d13xxxfb_pdata *pdata = NULL;
540 int ret = 0; 545 int ret = 0;
546 int i;
541 u8 revision; 547 u8 revision;
542 548
543 dbg("probe called: device is %p\n", pdev); 549 dbg("probe called: device is %p\n", pdev);
@@ -607,10 +613,19 @@ s1d13xxxfb_probe(struct platform_device *pdev)
607 goto bail; 613 goto bail;
608 } 614 }
609 615
610 revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE); 616 revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
611 if ((revision >> 2) != S1D_CHIP_REV) { 617
612 printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2)); 618 ret = -ENODEV;
613 ret = -ENODEV; 619
620 for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) {
621 if (revision == s1d13xxxfb_revisions[i])
622 ret = 0;
623 }
624
625 if (!ret)
626 printk(KERN_INFO PFX "chip revision %i\n", revision);
627 else {
628 printk(KERN_INFO PFX "unknown chip revision %i\n", revision);
614 goto bail; 629 goto bail;
615 } 630 }
616 631
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index f0598961c6b0..79cf0b1976aa 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -29,9 +29,9 @@
29#include <asm/div64.h> 29#include <asm/div64.h>
30 30
31#include <asm/mach/map.h> 31#include <asm/mach/map.h>
32#include <asm/arch/regs-lcd.h> 32#include <mach/regs-lcd.h>
33#include <asm/arch/regs-gpio.h> 33#include <mach/regs-gpio.h>
34#include <asm/arch/fb.h> 34#include <mach/fb.h>
35 35
36#ifdef CONFIG_PM 36#ifdef CONFIG_PM
37#include <linux/pm.h> 37#include <linux/pm.h>
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 2972f112dbed..4dcec48a1d78 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -11,7 +11,6 @@
11 * which is based on the code of neofb. 11 * which is based on the code of neofb.
12 */ 12 */
13 13
14#include <linux/version.h>
15#include <linux/module.h> 14#include <linux/module.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/errno.h> 16#include <linux/errno.h>
@@ -903,13 +902,13 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
903 /* Prepare PCI device */ 902 /* Prepare PCI device */
904 rc = pci_enable_device(dev); 903 rc = pci_enable_device(dev);
905 if (rc < 0) { 904 if (rc < 0) {
906 dev_err(info->dev, "cannot enable PCI device\n"); 905 dev_err(info->device, "cannot enable PCI device\n");
907 goto err_enable_device; 906 goto err_enable_device;
908 } 907 }
909 908
910 rc = pci_request_regions(dev, "s3fb"); 909 rc = pci_request_regions(dev, "s3fb");
911 if (rc < 0) { 910 if (rc < 0) {
912 dev_err(info->dev, "cannot reserve framebuffer region\n"); 911 dev_err(info->device, "cannot reserve framebuffer region\n");
913 goto err_request_regions; 912 goto err_request_regions;
914 } 913 }
915 914
@@ -921,7 +920,7 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
921 info->screen_base = pci_iomap(dev, 0, 0); 920 info->screen_base = pci_iomap(dev, 0, 0);
922 if (! info->screen_base) { 921 if (! info->screen_base) {
923 rc = -ENOMEM; 922 rc = -ENOMEM;
924 dev_err(info->dev, "iomap for framebuffer failed\n"); 923 dev_err(info->device, "iomap for framebuffer failed\n");
925 goto err_iomap; 924 goto err_iomap;
926 } 925 }
927 926
@@ -965,19 +964,19 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
965 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); 964 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
966 if (! ((rc == 1) || (rc == 2))) { 965 if (! ((rc == 1) || (rc == 2))) {
967 rc = -EINVAL; 966 rc = -EINVAL;
968 dev_err(info->dev, "mode %s not found\n", mode_option); 967 dev_err(info->device, "mode %s not found\n", mode_option);
969 goto err_find_mode; 968 goto err_find_mode;
970 } 969 }
971 970
972 rc = fb_alloc_cmap(&info->cmap, 256, 0); 971 rc = fb_alloc_cmap(&info->cmap, 256, 0);
973 if (rc < 0) { 972 if (rc < 0) {
974 dev_err(info->dev, "cannot allocate colormap\n"); 973 dev_err(info->device, "cannot allocate colormap\n");
975 goto err_alloc_cmap; 974 goto err_alloc_cmap;
976 } 975 }
977 976
978 rc = register_framebuffer(info); 977 rc = register_framebuffer(info);
979 if (rc < 0) { 978 if (rc < 0) {
980 dev_err(info->dev, "cannot register framebuffer\n"); 979 dev_err(info->device, "cannot register framebuffer\n");
981 goto err_reg_fb; 980 goto err_reg_fb;
982 } 981 }
983 982
@@ -1053,7 +1052,7 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
1053 struct fb_info *info = pci_get_drvdata(dev); 1052 struct fb_info *info = pci_get_drvdata(dev);
1054 struct s3fb_info *par = info->par; 1053 struct s3fb_info *par = info->par;
1055 1054
1056 dev_info(info->dev, "suspend\n"); 1055 dev_info(info->device, "suspend\n");
1057 1056
1058 acquire_console_sem(); 1057 acquire_console_sem();
1059 mutex_lock(&(par->open_lock)); 1058 mutex_lock(&(par->open_lock));
@@ -1085,7 +1084,7 @@ static int s3_pci_resume(struct pci_dev* dev)
1085 struct s3fb_info *par = info->par; 1084 struct s3fb_info *par = info->par;
1086 int err; 1085 int err;
1087 1086
1088 dev_info(info->dev, "resume\n"); 1087 dev_info(info->device, "resume\n");
1089 1088
1090 acquire_console_sem(); 1089 acquire_console_sem();
1091 mutex_lock(&(par->open_lock)); 1090 mutex_lock(&(par->open_lock));
@@ -1102,7 +1101,7 @@ static int s3_pci_resume(struct pci_dev* dev)
1102 if (err) { 1101 if (err) {
1103 mutex_unlock(&(par->open_lock)); 1102 mutex_unlock(&(par->open_lock));
1104 release_console_sem(); 1103 release_console_sem();
1105 dev_err(info->dev, "error %d enabling device for resume\n", err); 1104 dev_err(info->device, "error %d enabling device for resume\n", err);
1106 return err; 1105 return err;
1107 } 1106 }
1108 pci_set_master(dev); 1107 pci_set_master(dev);
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index ab2b2110478b..c052bd4c0b06 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -167,6 +167,7 @@
167#include <linux/string.h> 167#include <linux/string.h>
168#include <linux/interrupt.h> 168#include <linux/interrupt.h>
169#include <linux/slab.h> 169#include <linux/slab.h>
170#include <linux/mm.h>
170#include <linux/fb.h> 171#include <linux/fb.h>
171#include <linux/delay.h> 172#include <linux/delay.h>
172#include <linux/init.h> 173#include <linux/init.h>
@@ -174,12 +175,13 @@
174#include <linux/cpufreq.h> 175#include <linux/cpufreq.h>
175#include <linux/platform_device.h> 176#include <linux/platform_device.h>
176#include <linux/dma-mapping.h> 177#include <linux/dma-mapping.h>
178#include <linux/mutex.h>
177 179
178#include <asm/hardware.h> 180#include <mach/hardware.h>
179#include <asm/io.h> 181#include <asm/io.h>
180#include <asm/mach-types.h> 182#include <asm/mach-types.h>
181#include <asm/arch/assabet.h> 183#include <mach/assabet.h>
182#include <asm/arch/shannon.h> 184#include <mach/shannon.h>
183 185
184/* 186/*
185 * debugging? 187 * debugging?
@@ -1107,7 +1109,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
1107{ 1109{
1108 u_int old_state; 1110 u_int old_state;
1109 1111
1110 down(&fbi->ctrlr_sem); 1112 mutex_lock(&fbi->ctrlr_lock);
1111 1113
1112 old_state = fbi->state; 1114 old_state = fbi->state;
1113 1115
@@ -1192,7 +1194,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
1192 } 1194 }
1193 break; 1195 break;
1194 } 1196 }
1195 up(&fbi->ctrlr_sem); 1197 mutex_unlock(&fbi->ctrlr_lock);
1196} 1198}
1197 1199
1198/* 1200/*
@@ -1444,7 +1446,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
1444 1446
1445 init_waitqueue_head(&fbi->ctrlr_wait); 1447 init_waitqueue_head(&fbi->ctrlr_wait);
1446 INIT_WORK(&fbi->task, sa1100fb_task); 1448 INIT_WORK(&fbi->task, sa1100fb_task);
1447 init_MUTEX(&fbi->ctrlr_sem); 1449 mutex_init(&fbi->ctrlr_lock);
1448 1450
1449 return fbi; 1451 return fbi;
1450} 1452}
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index f465b27ed860..86831db9a042 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -100,7 +100,7 @@ struct sa1100fb_info {
100 100
101 volatile u_char state; 101 volatile u_char state;
102 volatile u_char task_state; 102 volatile u_char task_state;
103 struct semaphore ctrlr_sem; 103 struct mutex ctrlr_lock;
104 wait_queue_head_t ctrlr_wait; 104 wait_queue_head_t ctrlr_wait;
105 struct work_struct task; 105 struct work_struct task;
106 106
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
new file mode 100644
index 000000000000..8d0212da4514
--- /dev/null
+++ b/drivers/video/sh7760fb.c
@@ -0,0 +1,659 @@
1/*
2 * SH7760/SH7763 LCDC Framebuffer driver.
3 *
4 * (c) 2006-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net>
6 * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt!
13 *
14 * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de>
15 * for his original source and testing!
16 */
17
18#include <linux/completion.h>
19#include <linux/delay.h>
20#include <linux/dma-mapping.h>
21#include <linux/fb.h>
22#include <linux/interrupt.h>
23#include <linux/io.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27
28#include <asm/sh7760fb.h>
29
30struct sh7760fb_par {
31 void __iomem *base;
32 int irq;
33
34 struct sh7760fb_platdata *pd; /* display information */
35
36 dma_addr_t fbdma; /* physical address */
37
38 int rot; /* rotation enabled? */
39
40 u32 pseudo_palette[16];
41
42 struct platform_device *dev;
43 struct resource *ioarea;
44 struct completion vsync; /* vsync irq event */
45};
46
47static irqreturn_t sh7760fb_irq(int irq, void *data)
48{
49 struct completion *c = data;
50
51 complete(c);
52
53 return IRQ_HANDLED;
54}
55
56static void sh7760fb_wait_vsync(struct fb_info *info)
57{
58 struct sh7760fb_par *par = info->par;
59
60 if (par->pd->novsync)
61 return;
62
63 iowrite16(ioread16(par->base + LDINTR) & ~VINT_CHECK,
64 par->base + LDINTR);
65
66 if (par->irq < 0) {
67 /* poll for vert. retrace: status bit is sticky */
68 while (!(ioread16(par->base + LDINTR) & VINT_CHECK))
69 cpu_relax();
70 } else {
71 /* a "wait_for_irq_event(par->irq)" would be extremely nice */
72 init_completion(&par->vsync);
73 enable_irq(par->irq);
74 wait_for_completion(&par->vsync);
75 disable_irq_nosync(par->irq);
76 }
77}
78
79/* wait_for_lps - wait until power supply has reached a certain state. */
80static int wait_for_lps(struct sh7760fb_par *par, int val)
81{
82 int i = 100;
83 while (--i && ((ioread16(par->base + LDPMMR) & 3) != val))
84 msleep(1);
85
86 if (i <= 0)
87 return -ETIMEDOUT;
88
89 return 0;
90}
91
92/* en/disable the LCDC */
93static int sh7760fb_blank(int blank, struct fb_info *info)
94{
95 struct sh7760fb_par *par = info->par;
96 struct sh7760fb_platdata *pd = par->pd;
97 unsigned short cntr = ioread16(par->base + LDCNTR);
98 unsigned short intr = ioread16(par->base + LDINTR);
99 int lps;
100
101 if (blank == FB_BLANK_UNBLANK) {
102 intr |= VINT_START;
103 cntr = LDCNTR_DON2 | LDCNTR_DON;
104 lps = 3;
105 } else {
106 intr &= ~VINT_START;
107 cntr = LDCNTR_DON2;
108 lps = 0;
109 }
110
111 if (pd->blank)
112 pd->blank(blank);
113
114 iowrite16(intr, par->base + LDINTR);
115 iowrite16(cntr, par->base + LDCNTR);
116
117 return wait_for_lps(par, lps);
118}
119
120/* set color registers */
121static int sh7760fb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
122{
123 struct sh7760fb_par *par = info->par;
124 u32 s = cmap->start;
125 u32 l = cmap->len;
126 u16 *r = cmap->red;
127 u16 *g = cmap->green;
128 u16 *b = cmap->blue;
129 u32 col, tmo;
130 int ret;
131
132 ret = 0;
133
134 sh7760fb_wait_vsync(info);
135
136 /* request palette access */
137 iowrite16(LDPALCR_PALEN, par->base + LDPALCR);
138
139 /* poll for access grant */
140 tmo = 100;
141 while (!(ioread16(par->base + LDPALCR) & LDPALCR_PALS) && (--tmo))
142 cpu_relax();
143
144 if (!tmo) {
145 ret = 1;
146 dev_dbg(info->dev, "no palette access!\n");
147 goto out;
148 }
149
150 while (l && (s < 256)) {
151 col = ((*r) & 0xff) << 16;
152 col |= ((*g) & 0xff) << 8;
153 col |= ((*b) & 0xff);
154 col &= SH7760FB_PALETTE_MASK;
155 iowrite32(col, par->base + LDPR(s));
156
157 if (s < 16)
158 ((u32 *) (info->pseudo_palette))[s] = s;
159
160 s++;
161 l--;
162 r++;
163 g++;
164 b++;
165 }
166out:
167 iowrite16(0, par->base + LDPALCR);
168 return ret;
169}
170
171static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
172 unsigned long stride)
173{
174 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
175 strcpy(fix->id, "sh7760-lcdc");
176
177 fix->smem_start = (unsigned long)info->screen_base;
178 fix->smem_len = info->screen_size;
179
180 fix->line_length = stride;
181}
182
183static int sh7760fb_get_color_info(struct device *dev,
184 u16 lddfr, int *bpp, int *gray)
185{
186 int lbpp, lgray;
187
188 lgray = lbpp = 0;
189
190 switch (lddfr & LDDFR_COLOR_MASK) {
191 case LDDFR_1BPP_MONO:
192 lgray = 1;
193 lbpp = 1;
194 break;
195 case LDDFR_2BPP_MONO:
196 lgray = 1;
197 lbpp = 2;
198 break;
199 case LDDFR_4BPP_MONO:
200 lgray = 1;
201 case LDDFR_4BPP:
202 lbpp = 4;
203 break;
204 case LDDFR_6BPP_MONO:
205 lgray = 1;
206 case LDDFR_8BPP:
207 lbpp = 8;
208 break;
209 case LDDFR_16BPP_RGB555:
210 case LDDFR_16BPP_RGB565:
211 lbpp = 16;
212 lgray = 0;
213 break;
214 default:
215 dev_dbg(dev, "unsupported LDDFR bit depth.\n");
216 return -EINVAL;
217 }
218
219 if (bpp)
220 *bpp = lbpp;
221 if (gray)
222 *gray = lgray;
223
224 return 0;
225}
226
227static int sh7760fb_check_var(struct fb_var_screeninfo *var,
228 struct fb_info *info)
229{
230 struct fb_fix_screeninfo *fix = &info->fix;
231 struct sh7760fb_par *par = info->par;
232 int ret, bpp;
233
234 /* get color info from register value */
235 ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
236 if (ret)
237 return ret;
238
239 var->bits_per_pixel = bpp;
240
241 if ((var->grayscale) && (var->bits_per_pixel == 1))
242 fix->visual = FB_VISUAL_MONO10;
243 else if (var->bits_per_pixel >= 15)
244 fix->visual = FB_VISUAL_TRUECOLOR;
245 else
246 fix->visual = FB_VISUAL_PSEUDOCOLOR;
247
248 /* TODO: add some more validation here */
249 return 0;
250}
251
252/*
253 * sh7760fb_set_par - set videomode.
254 *
255 * NOTE: The rotation, grayscale and DSTN codepaths are
256 * totally untested!
257 */
258static int sh7760fb_set_par(struct fb_info *info)
259{
260 struct sh7760fb_par *par = info->par;
261 struct fb_videomode *vm = par->pd->def_mode;
262 unsigned long sbase, dstn_off, ldsarl, stride;
263 unsigned short hsynp, hsynw, htcn, hdcn;
264 unsigned short vsynp, vsynw, vtln, vdln;
265 unsigned short lddfr, ldmtr;
266 int ret, bpp, gray;
267
268 par->rot = par->pd->rotate;
269
270 /* rotate only works with xres <= 320 */
271 if (par->rot && (vm->xres > 320)) {
272 dev_dbg(info->dev, "rotation disabled due to display size\n");
273 par->rot = 0;
274 }
275
276 /* calculate LCDC reg vals from display parameters */
277 hsynp = vm->right_margin + vm->xres;
278 hsynw = vm->hsync_len;
279 htcn = vm->left_margin + hsynp + hsynw;
280 hdcn = vm->xres;
281 vsynp = vm->lower_margin + vm->yres;
282 vsynw = vm->vsync_len;
283 vtln = vm->upper_margin + vsynp + vsynw;
284 vdln = vm->yres;
285
286 /* get color info from register value */
287 ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, &gray);
288 if (ret)
289 return ret;
290
291 dev_dbg(info->dev, "%dx%d %dbpp %s (orientation %s)\n", hdcn,
292 vdln, bpp, gray ? "grayscale" : "color",
293 par->rot ? "rotated" : "normal");
294
295#ifdef CONFIG_CPU_LITTLE_ENDIAN
296 lddfr = par->pd->lddfr | (1 << 8);
297#else
298 lddfr = par->pd->lddfr & ~(1 << 8);
299#endif
300
301 ldmtr = par->pd->ldmtr;
302
303 if (!(vm->sync & FB_SYNC_HOR_HIGH_ACT))
304 ldmtr |= LDMTR_CL1POL;
305 if (!(vm->sync & FB_SYNC_VERT_HIGH_ACT))
306 ldmtr |= LDMTR_FLMPOL;
307
308 /* shut down LCDC before changing display parameters */
309 sh7760fb_blank(FB_BLANK_POWERDOWN, info);
310
311 iowrite16(par->pd->ldickr, par->base + LDICKR); /* pixclock */
312 iowrite16(ldmtr, par->base + LDMTR); /* polarities */
313 iowrite16(lddfr, par->base + LDDFR); /* color/depth */
314 iowrite16((par->rot ? 1 << 13 : 0), par->base + LDSMR); /* rotate */
315 iowrite16(par->pd->ldpmmr, par->base + LDPMMR); /* Power Management */
316 iowrite16(par->pd->ldpspr, par->base + LDPSPR); /* Power Supply Ctrl */
317
318 /* display resolution */
319 iowrite16(((htcn >> 3) - 1) | (((hdcn >> 3) - 1) << 8),
320 par->base + LDHCNR);
321 iowrite16(vdln - 1, par->base + LDVDLNR);
322 iowrite16(vtln - 1, par->base + LDVTLNR);
323 /* h/v sync signals */
324 iowrite16((vsynp - 1) | ((vsynw - 1) << 12), par->base + LDVSYNR);
325 iowrite16(((hsynp >> 3) - 1) | (((hsynw >> 3) - 1) << 12),
326 par->base + LDHSYNR);
327 /* AC modulation sig */
328 iowrite16(par->pd->ldaclnr, par->base + LDACLNR);
329
330 stride = (par->rot) ? vtln : hdcn;
331 if (!gray)
332 stride *= (bpp + 7) >> 3;
333 else {
334 if (bpp == 1)
335 stride >>= 3;
336 else if (bpp == 2)
337 stride >>= 2;
338 else if (bpp == 4)
339 stride >>= 1;
340 /* 6 bpp == 8 bpp */
341 }
342
343 /* if rotated, stride must be power of 2 */
344 if (par->rot) {
345 unsigned long bit = 1 << 31;
346 while (bit) {
347 if (stride & bit)
348 break;
349 bit >>= 1;
350 }
351 if (stride & ~bit)
352 stride = bit << 1; /* not P-o-2, round up */
353 }
354 iowrite16(stride, par->base + LDLAOR);
355
356 /* set display mem start address */
357 sbase = (unsigned long)par->fbdma;
358 if (par->rot)
359 sbase += (hdcn - 1) * stride;
360
361 iowrite32(sbase, par->base + LDSARU);
362
363 /*
364 * for DSTN need to set address for lower half.
365 * I (mlau) don't know which address to set it to,
366 * so I guessed at (stride * yres/2).
367 */
368 if (((ldmtr & 0x003f) >= LDMTR_DSTN_MONO_8) &&
369 ((ldmtr & 0x003f) <= LDMTR_DSTN_COLOR_16)) {
370
371 dev_dbg(info->dev, " ***** DSTN untested! *****\n");
372
373 dstn_off = stride;
374 if (par->rot)
375 dstn_off *= hdcn >> 1;
376 else
377 dstn_off *= vdln >> 1;
378
379 ldsarl = sbase + dstn_off;
380 } else
381 ldsarl = 0;
382
383 iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */
384
385 encode_fix(&info->fix, info, stride);
386 sh7760fb_check_var(&info->var, info);
387
388 sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
389
390 dev_dbg(info->dev, "hdcn : %6d htcn : %6d\n", hdcn, htcn);
391 dev_dbg(info->dev, "hsynw : %6d hsynp : %6d\n", hsynw, hsynp);
392 dev_dbg(info->dev, "vdln : %6d vtln : %6d\n", vdln, vtln);
393 dev_dbg(info->dev, "vsynw : %6d vsynp : %6d\n", vsynw, vsynp);
394 dev_dbg(info->dev, "clksrc: %6d clkdiv: %6d\n",
395 (par->pd->ldickr >> 12) & 3, par->pd->ldickr & 0x1f);
396 dev_dbg(info->dev, "ldpmmr: 0x%04x ldpspr: 0x%04x\n", par->pd->ldpmmr,
397 par->pd->ldpspr);
398 dev_dbg(info->dev, "ldmtr : 0x%04x lddfr : 0x%04x\n", ldmtr, lddfr);
399 dev_dbg(info->dev, "ldlaor: %ld\n", stride);
400 dev_dbg(info->dev, "ldsaru: 0x%08lx ldsarl: 0x%08lx\n", sbase, ldsarl);
401
402 return 0;
403}
404
405static struct fb_ops sh7760fb_ops = {
406 .owner = THIS_MODULE,
407 .fb_blank = sh7760fb_blank,
408 .fb_check_var = sh7760fb_check_var,
409 .fb_setcmap = sh7760fb_setcmap,
410 .fb_set_par = sh7760fb_set_par,
411 .fb_fillrect = cfb_fillrect,
412 .fb_copyarea = cfb_copyarea,
413 .fb_imageblit = cfb_imageblit,
414};
415
416static void sh7760fb_free_mem(struct fb_info *info)
417{
418 struct sh7760fb_par *par = info->par;
419
420 if (!info->screen_base)
421 return;
422
423 dma_free_coherent(info->dev, info->screen_size,
424 info->screen_base, par->fbdma);
425
426 par->fbdma = 0;
427 info->screen_base = NULL;
428 info->screen_size = 0;
429}
430
431/* allocate the framebuffer memory. This memory must be in Area3,
432 * (dictated by the DMA engine) and contiguous, at a 512 byte boundary.
433 */
434static int sh7760fb_alloc_mem(struct fb_info *info)
435{
436 struct sh7760fb_par *par = info->par;
437 void *fbmem;
438 unsigned long vram;
439 int ret, bpp;
440
441 if (info->screen_base)
442 return 0;
443
444 /* get color info from register value */
445 ret = sh7760fb_get_color_info(info->dev, par->pd->lddfr, &bpp, NULL);
446 if (ret) {
447 printk(KERN_ERR "colinfo\n");
448 return ret;
449 }
450
451 /* min VRAM: xres_min = 16, yres_min = 1, bpp = 1: 2byte -> 1 page
452 max VRAM: xres_max = 1024, yres_max = 1024, bpp = 16: 2MB */
453
454 vram = info->var.xres * info->var.yres;
455 if (info->var.grayscale) {
456 if (bpp == 1)
457 vram >>= 3;
458 else if (bpp == 2)
459 vram >>= 2;
460 else if (bpp == 4)
461 vram >>= 1;
462 } else if (bpp > 8)
463 vram *= 2;
464 if ((vram < 1) || (vram > 1024 * 2048)) {
465 dev_dbg(info->dev, "too much VRAM required. Check settings\n");
466 return -ENODEV;
467 }
468
469 if (vram < PAGE_SIZE)
470 vram = PAGE_SIZE;
471
472 fbmem = dma_alloc_coherent(info->dev, vram, &par->fbdma, GFP_KERNEL);
473
474 if (!fbmem)
475 return -ENOMEM;
476
477 if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
478 sh7760fb_free_mem(info);
479 dev_err(info->dev, "kernel gave me memory at 0x%08lx, which is"
480 "unusable for the LCDC\n", (unsigned long)par->fbdma);
481 return -ENOMEM;
482 }
483
484 info->screen_base = fbmem;
485 info->screen_size = vram;
486
487 return 0;
488}
489
490static int __devinit sh7760fb_probe(struct platform_device *pdev)
491{
492 struct fb_info *info;
493 struct resource *res;
494 struct sh7760fb_par *par;
495 int ret;
496
497 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
498 if (unlikely(res == NULL)) {
499 dev_err(&pdev->dev, "invalid resource\n");
500 return -EINVAL;
501 }
502
503 info = framebuffer_alloc(sizeof(struct sh7760fb_par), &pdev->dev);
504 if (!info)
505 return -ENOMEM;
506
507 par = info->par;
508 par->dev = pdev;
509
510 par->pd = pdev->dev.platform_data;
511 if (!par->pd) {
512 dev_dbg(info->dev, "no display setup data!\n");
513 ret = -ENODEV;
514 goto out_fb;
515 }
516
517 par->ioarea = request_mem_region(res->start,
518 (res->end - res->start), pdev->name);
519 if (!par->ioarea) {
520 dev_err(&pdev->dev, "mmio area busy\n");
521 ret = -EBUSY;
522 goto out_fb;
523 }
524
525 par->base = ioremap_nocache(res->start, res->end - res->start + 1);
526 if (!par->base) {
527 dev_err(&pdev->dev, "cannot remap\n");
528 ret = -ENODEV;
529 goto out_res;
530 }
531
532 iowrite16(0, par->base + LDINTR); /* disable vsync irq */
533 par->irq = platform_get_irq(pdev, 0);
534 if (par->irq >= 0) {
535 ret = request_irq(par->irq, sh7760fb_irq, 0,
536 "sh7760-lcdc", &par->vsync);
537 if (ret) {
538 dev_err(&pdev->dev, "cannot grab IRQ\n");
539 par->irq = -ENXIO;
540 } else
541 disable_irq_nosync(par->irq);
542 }
543
544 fb_videomode_to_var(&info->var, par->pd->def_mode);
545
546 ret = sh7760fb_alloc_mem(info);
547 if (ret) {
548 dev_dbg(info->dev, "framebuffer memory allocation failed!\n");
549 goto out_unmap;
550 }
551
552 info->pseudo_palette = par->pseudo_palette;
553
554 /* fixup color register bitpositions. These are fixed by hardware */
555 info->var.red.offset = 11;
556 info->var.red.length = 5;
557 info->var.red.msb_right = 0;
558
559 info->var.green.offset = 5;
560 info->var.green.length = 6;
561 info->var.green.msb_right = 0;
562
563 info->var.blue.offset = 0;
564 info->var.blue.length = 5;
565 info->var.blue.msb_right = 0;
566
567 info->var.transp.offset = 0;
568 info->var.transp.length = 0;
569 info->var.transp.msb_right = 0;
570
571 /* set the DON2 bit now, before cmap allocation, as it will randomize
572 * palette memory.
573 */
574 iowrite16(LDCNTR_DON2, par->base + LDCNTR);
575 info->fbops = &sh7760fb_ops;
576
577 ret = fb_alloc_cmap(&info->cmap, 256, 0);
578 if (ret) {
579 dev_dbg(info->dev, "Unable to allocate cmap memory\n");
580 goto out_mem;
581 }
582
583 ret = register_framebuffer(info);
584 if (ret < 0) {
585 dev_dbg(info->dev, "cannot register fb!\n");
586 goto out_cmap;
587 }
588 platform_set_drvdata(pdev, info);
589
590 printk(KERN_INFO "%s: memory at phys 0x%08lx-0x%08lx, size %ld KiB\n",
591 pdev->name,
592 (unsigned long)par->fbdma,
593 (unsigned long)(par->fbdma + info->screen_size - 1),
594 info->screen_size >> 10);
595
596 return 0;
597
598out_cmap:
599 sh7760fb_blank(FB_BLANK_POWERDOWN, info);
600 fb_dealloc_cmap(&info->cmap);
601out_mem:
602 sh7760fb_free_mem(info);
603out_unmap:
604 if (par->irq >= 0)
605 free_irq(par->irq, &par->vsync);
606 iounmap(par->base);
607out_res:
608 release_resource(par->ioarea);
609 kfree(par->ioarea);
610out_fb:
611 framebuffer_release(info);
612 return ret;
613}
614
615static int __devexit sh7760fb_remove(struct platform_device *dev)
616{
617 struct fb_info *info = platform_get_drvdata(dev);
618 struct sh7760fb_par *par = info->par;
619
620 sh7760fb_blank(FB_BLANK_POWERDOWN, info);
621 unregister_framebuffer(info);
622 fb_dealloc_cmap(&info->cmap);
623 sh7760fb_free_mem(info);
624 if (par->irq >= 0)
625 free_irq(par->irq, par);
626 iounmap(par->base);
627 release_resource(par->ioarea);
628 kfree(par->ioarea);
629 framebuffer_release(info);
630 platform_set_drvdata(dev, NULL);
631
632 return 0;
633}
634
635static struct platform_driver sh7760_lcdc_driver = {
636 .driver = {
637 .name = "sh7760-lcdc",
638 .owner = THIS_MODULE,
639 },
640 .probe = sh7760fb_probe,
641 .remove = __devexit_p(sh7760fb_remove),
642};
643
644static int __init sh7760fb_init(void)
645{
646 return platform_driver_register(&sh7760_lcdc_driver);
647}
648
649static void __exit sh7760fb_exit(void)
650{
651 platform_driver_unregister(&sh7760_lcdc_driver);
652}
653
654module_init(sh7760fb_init);
655module_exit(sh7760fb_exit);
656
657MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
658MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
659MODULE_LICENSE("GPL");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
new file mode 100644
index 000000000000..efff672fd7b8
--- /dev/null
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -0,0 +1,737 @@
1/*
2 * SuperH Mobile LCDC Framebuffer
3 *
4 * Copyright (c) 2008 Magnus Damm
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/delay.h>
14#include <linux/mm.h>
15#include <linux/fb.h>
16#include <linux/clk.h>
17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h>
19#include <video/sh_mobile_lcdc.h>
20
21#define PALETTE_NR 16
22
23struct sh_mobile_lcdc_priv;
24struct sh_mobile_lcdc_chan {
25 struct sh_mobile_lcdc_priv *lcdc;
26 unsigned long *reg_offs;
27 unsigned long ldmt1r_value;
28 unsigned long enabled; /* ME and SE in LDCNT2R */
29 struct sh_mobile_lcdc_chan_cfg cfg;
30 u32 pseudo_palette[PALETTE_NR];
31 struct fb_info info;
32 dma_addr_t dma_handle;
33};
34
35struct sh_mobile_lcdc_priv {
36 void __iomem *base;
37#ifdef CONFIG_HAVE_CLK
38 struct clk *clk;
39#endif
40 unsigned long lddckr;
41 struct sh_mobile_lcdc_chan ch[2];
42};
43
44/* shared registers */
45#define _LDDCKR 0x410
46#define _LDDCKSTPR 0x414
47#define _LDINTR 0x468
48#define _LDSR 0x46c
49#define _LDCNT1R 0x470
50#define _LDCNT2R 0x474
51#define _LDDDSR 0x47c
52#define _LDDWD0R 0x800
53#define _LDDRDR 0x840
54#define _LDDWAR 0x900
55#define _LDDRAR 0x904
56
57/* per-channel registers */
58enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
59 LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR };
60
61static unsigned long lcdc_offs_mainlcd[] = {
62 [LDDCKPAT1R] = 0x400,
63 [LDDCKPAT2R] = 0x404,
64 [LDMT1R] = 0x418,
65 [LDMT2R] = 0x41c,
66 [LDMT3R] = 0x420,
67 [LDDFR] = 0x424,
68 [LDSM1R] = 0x428,
69 [LDSA1R] = 0x430,
70 [LDMLSR] = 0x438,
71 [LDHCNR] = 0x448,
72 [LDHSYNR] = 0x44c,
73 [LDVLNR] = 0x450,
74 [LDVSYNR] = 0x454,
75 [LDPMR] = 0x460,
76};
77
78static unsigned long lcdc_offs_sublcd[] = {
79 [LDDCKPAT1R] = 0x408,
80 [LDDCKPAT2R] = 0x40c,
81 [LDMT1R] = 0x600,
82 [LDMT2R] = 0x604,
83 [LDMT3R] = 0x608,
84 [LDDFR] = 0x60c,
85 [LDSM1R] = 0x610,
86 [LDSA1R] = 0x618,
87 [LDMLSR] = 0x620,
88 [LDHCNR] = 0x624,
89 [LDHSYNR] = 0x628,
90 [LDVLNR] = 0x62c,
91 [LDVSYNR] = 0x630,
92 [LDPMR] = 0x63c,
93};
94
95#define START_LCDC 0x00000001
96#define LCDC_RESET 0x00000100
97#define DISPLAY_BEU 0x00000008
98#define LCDC_ENABLE 0x00000001
99
100static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
101 int reg_nr, unsigned long data)
102{
103 iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]);
104}
105
106static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
107 int reg_nr)
108{
109 return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
110}
111
112static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
113 unsigned long reg_offs, unsigned long data)
114{
115 iowrite32(data, priv->base + reg_offs);
116}
117
118static unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv,
119 unsigned long reg_offs)
120{
121 return ioread32(priv->base + reg_offs);
122}
123
124static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
125 unsigned long reg_offs,
126 unsigned long mask, unsigned long until)
127{
128 while ((lcdc_read(priv, reg_offs) & mask) != until)
129 cpu_relax();
130}
131
132static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
133{
134 return chan->cfg.chan == LCDC_CHAN_SUBLCD;
135}
136
137static void lcdc_sys_write_index(void *handle, unsigned long data)
138{
139 struct sh_mobile_lcdc_chan *ch = handle;
140
141 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000);
142 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
143 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
144}
145
146static void lcdc_sys_write_data(void *handle, unsigned long data)
147{
148 struct sh_mobile_lcdc_chan *ch = handle;
149
150 lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000);
151 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
152 lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
153}
154
155static unsigned long lcdc_sys_read_data(void *handle)
156{
157 struct sh_mobile_lcdc_chan *ch = handle;
158
159 lcdc_write(ch->lcdc, _LDDRDR, 0x01000000);
160 lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0);
161 lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0));
162 udelay(1);
163
164 return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff;
165}
166
167struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
168 lcdc_sys_write_index,
169 lcdc_sys_write_data,
170 lcdc_sys_read_data,
171};
172
173static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
174 int start)
175{
176 unsigned long tmp = lcdc_read(priv, _LDCNT2R);
177 int k;
178
179 /* start or stop the lcdc */
180 if (start)
181 lcdc_write(priv, _LDCNT2R, tmp | START_LCDC);
182 else
183 lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC);
184
185 /* wait until power is applied/stopped on all channels */
186 for (k = 0; k < ARRAY_SIZE(priv->ch); k++)
187 if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled)
188 while (1) {
189 tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3;
190 if (start && tmp == 3)
191 break;
192 if (!start && tmp == 0)
193 break;
194 cpu_relax();
195 }
196
197 if (!start)
198 lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
199}
200
201static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
202{
203 struct sh_mobile_lcdc_chan *ch;
204 struct fb_videomode *lcd_cfg;
205 struct sh_mobile_lcdc_board_cfg *board_cfg;
206 unsigned long tmp;
207 int k, m;
208 int ret = 0;
209
210 /* reset */
211 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET);
212 lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0);
213
214 /* enable LCDC channels */
215 tmp = lcdc_read(priv, _LDCNT2R);
216 tmp |= priv->ch[0].enabled;
217 tmp |= priv->ch[1].enabled;
218 lcdc_write(priv, _LDCNT2R, tmp);
219
220 /* read data from external memory, avoid using the BEU for now */
221 lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU);
222
223 /* stop the lcdc first */
224 sh_mobile_lcdc_start_stop(priv, 0);
225
226 /* configure clocks */
227 tmp = priv->lddckr;
228 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
229 ch = &priv->ch[k];
230
231 if (!priv->ch[k].enabled)
232 continue;
233
234 m = ch->cfg.clock_divider;
235 if (!m)
236 continue;
237
238 if (m == 1)
239 m = 1 << 6;
240 tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0);
241
242 lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000);
243 lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1);
244 }
245
246 lcdc_write(priv, _LDDCKR, tmp);
247
248 /* start dotclock again */
249 lcdc_write(priv, _LDDCKSTPR, 0);
250 lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0);
251
252 /* interrupts are disabled */
253 lcdc_write(priv, _LDINTR, 0);
254
255 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
256 ch = &priv->ch[k];
257 lcd_cfg = &ch->cfg.lcd_cfg;
258
259 if (!ch->enabled)
260 continue;
261
262 tmp = ch->ldmt1r_value;
263 tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
264 tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
265 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
266 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
267 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
268 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
269 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
270 lcdc_write_chan(ch, LDMT1R, tmp);
271
272 /* setup SYS bus */
273 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
274 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
275
276 /* horizontal configuration */
277 tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
278 tmp += lcd_cfg->left_margin;
279 tmp += lcd_cfg->right_margin;
280 tmp /= 8; /* HTCN */
281 tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
282 lcdc_write_chan(ch, LDHCNR, tmp);
283
284 tmp = lcd_cfg->xres;
285 tmp += lcd_cfg->right_margin;
286 tmp /= 8; /* HSYNP */
287 tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
288 lcdc_write_chan(ch, LDHSYNR, tmp);
289
290 /* power supply */
291 lcdc_write_chan(ch, LDPMR, 0);
292
293 /* vertical configuration */
294 tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
295 tmp += lcd_cfg->upper_margin;
296 tmp += lcd_cfg->lower_margin; /* VTLN */
297 tmp |= lcd_cfg->yres << 16; /* VDLN */
298 lcdc_write_chan(ch, LDVLNR, tmp);
299
300 tmp = lcd_cfg->yres;
301 tmp += lcd_cfg->lower_margin; /* VSYNP */
302 tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
303 lcdc_write_chan(ch, LDVSYNR, tmp);
304
305 board_cfg = &ch->cfg.board_cfg;
306 if (board_cfg->setup_sys)
307 ret = board_cfg->setup_sys(board_cfg->board_data, ch,
308 &sh_mobile_lcdc_sys_bus_ops);
309 if (ret)
310 return ret;
311 }
312
313 /* --- display_lcdc_data() --- */
314 lcdc_write(priv, _LDINTR, 0x00000f00);
315
316 /* word and long word swap */
317 lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
318
319 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
320 ch = &priv->ch[k];
321
322 if (!priv->ch[k].enabled)
323 continue;
324
325 /* set bpp format in PKF[4:0] */
326 tmp = lcdc_read_chan(ch, LDDFR);
327 tmp &= ~(0x0001001f);
328 tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0;
329 lcdc_write_chan(ch, LDDFR, tmp);
330
331 /* point out our frame buffer */
332 lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start);
333
334 /* set line size */
335 lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length);
336
337 /* continuous read mode */
338 lcdc_write_chan(ch, LDSM1R, 0);
339 }
340
341 /* display output */
342 lcdc_write(priv, _LDCNT1R, LCDC_ENABLE);
343
344 /* start the lcdc */
345 sh_mobile_lcdc_start_stop(priv, 1);
346
347 /* tell the board code to enable the panel */
348 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
349 ch = &priv->ch[k];
350 board_cfg = &ch->cfg.board_cfg;
351 if (board_cfg->display_on)
352 board_cfg->display_on(board_cfg->board_data);
353 }
354
355 return 0;
356}
357
358static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
359{
360 struct sh_mobile_lcdc_chan *ch;
361 struct sh_mobile_lcdc_board_cfg *board_cfg;
362 int k;
363
364 /* tell the board code to disable the panel */
365 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
366 ch = &priv->ch[k];
367 board_cfg = &ch->cfg.board_cfg;
368 if (board_cfg->display_off)
369 board_cfg->display_off(board_cfg->board_data);
370 }
371
372 /* stop the lcdc */
373 sh_mobile_lcdc_start_stop(priv, 0);
374}
375
376static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
377{
378 int ifm, miftyp;
379
380 switch (ch->cfg.interface_type) {
381 case RGB8: ifm = 0; miftyp = 0; break;
382 case RGB9: ifm = 0; miftyp = 4; break;
383 case RGB12A: ifm = 0; miftyp = 5; break;
384 case RGB12B: ifm = 0; miftyp = 6; break;
385 case RGB16: ifm = 0; miftyp = 7; break;
386 case RGB18: ifm = 0; miftyp = 10; break;
387 case RGB24: ifm = 0; miftyp = 11; break;
388 case SYS8A: ifm = 1; miftyp = 0; break;
389 case SYS8B: ifm = 1; miftyp = 1; break;
390 case SYS8C: ifm = 1; miftyp = 2; break;
391 case SYS8D: ifm = 1; miftyp = 3; break;
392 case SYS9: ifm = 1; miftyp = 4; break;
393 case SYS12: ifm = 1; miftyp = 5; break;
394 case SYS16A: ifm = 1; miftyp = 7; break;
395 case SYS16B: ifm = 1; miftyp = 8; break;
396 case SYS16C: ifm = 1; miftyp = 9; break;
397 case SYS18: ifm = 1; miftyp = 10; break;
398 case SYS24: ifm = 1; miftyp = 11; break;
399 default: goto bad;
400 }
401
402 /* SUBLCD only supports SYS interface */
403 if (lcdc_chan_is_sublcd(ch)) {
404 if (ifm == 0)
405 goto bad;
406 else
407 ifm = 0;
408 }
409
410 ch->ldmt1r_value = (ifm << 12) | miftyp;
411 return 0;
412 bad:
413 return -EINVAL;
414}
415
416static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
417 struct sh_mobile_lcdc_priv *priv)
418{
419 char *str;
420 int icksel;
421
422 switch (clock_source) {
423 case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break;
424 case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break;
425 case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break;
426 default:
427 return -EINVAL;
428 }
429
430 priv->lddckr = icksel << 16;
431
432#ifdef CONFIG_HAVE_CLK
433 if (str) {
434 priv->clk = clk_get(dev, str);
435 if (IS_ERR(priv->clk)) {
436 dev_err(dev, "cannot get clock %s\n", str);
437 return PTR_ERR(priv->clk);
438 }
439
440 clk_enable(priv->clk);
441 }
442#endif
443
444 return 0;
445}
446
447static int sh_mobile_lcdc_setcolreg(u_int regno,
448 u_int red, u_int green, u_int blue,
449 u_int transp, struct fb_info *info)
450{
451 u32 *palette = info->pseudo_palette;
452
453 if (regno >= PALETTE_NR)
454 return -EINVAL;
455
456 /* only FB_VISUAL_TRUECOLOR supported */
457
458 red >>= 16 - info->var.red.length;
459 green >>= 16 - info->var.green.length;
460 blue >>= 16 - info->var.blue.length;
461 transp >>= 16 - info->var.transp.length;
462
463 palette[regno] = (red << info->var.red.offset) |
464 (green << info->var.green.offset) |
465 (blue << info->var.blue.offset) |
466 (transp << info->var.transp.offset);
467
468 return 0;
469}
470
471static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
472 .id = "SH Mobile LCDC",
473 .type = FB_TYPE_PACKED_PIXELS,
474 .visual = FB_VISUAL_TRUECOLOR,
475 .accel = FB_ACCEL_NONE,
476};
477
478static struct fb_ops sh_mobile_lcdc_ops = {
479 .fb_setcolreg = sh_mobile_lcdc_setcolreg,
480 .fb_fillrect = cfb_fillrect,
481 .fb_copyarea = cfb_copyarea,
482 .fb_imageblit = cfb_imageblit,
483};
484
485static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
486{
487 switch (bpp) {
488 case 16: /* PKF[4:0] = 00011 - RGB 565 */
489 var->red.offset = 11;
490 var->red.length = 5;
491 var->green.offset = 5;
492 var->green.length = 6;
493 var->blue.offset = 0;
494 var->blue.length = 5;
495 var->transp.offset = 0;
496 var->transp.length = 0;
497 break;
498
499 case 32: /* PKF[4:0] = 00000 - RGB 888
500 * sh7722 pdf says 00RRGGBB but reality is GGBB00RR
501 * this may be because LDDDSR has word swap enabled..
502 */
503 var->red.offset = 0;
504 var->red.length = 8;
505 var->green.offset = 24;
506 var->green.length = 8;
507 var->blue.offset = 16;
508 var->blue.length = 8;
509 var->transp.offset = 0;
510 var->transp.length = 0;
511 break;
512 default:
513 return -EINVAL;
514 }
515 var->bits_per_pixel = bpp;
516 var->red.msb_right = 0;
517 var->green.msb_right = 0;
518 var->blue.msb_right = 0;
519 var->transp.msb_right = 0;
520 return 0;
521}
522
523static int sh_mobile_lcdc_remove(struct platform_device *pdev);
524
525static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
526{
527 struct fb_info *info;
528 struct sh_mobile_lcdc_priv *priv;
529 struct sh_mobile_lcdc_info *pdata;
530 struct sh_mobile_lcdc_chan_cfg *cfg;
531 struct resource *res;
532 int error;
533 void *buf;
534 int i, j;
535
536 if (!pdev->dev.platform_data) {
537 dev_err(&pdev->dev, "no platform data defined\n");
538 error = -EINVAL;
539 goto err0;
540 }
541
542 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
543 if (res == NULL) {
544 dev_err(&pdev->dev, "cannot find IO resource\n");
545 error = -ENOENT;
546 goto err0;
547 }
548
549 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
550 if (!priv) {
551 dev_err(&pdev->dev, "cannot allocate device data\n");
552 error = -ENOMEM;
553 goto err0;
554 }
555
556 platform_set_drvdata(pdev, priv);
557 pdata = pdev->dev.platform_data;
558
559 j = 0;
560 for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) {
561 priv->ch[j].lcdc = priv;
562 memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i]));
563
564 error = sh_mobile_lcdc_check_interface(&priv->ch[i]);
565 if (error) {
566 dev_err(&pdev->dev, "unsupported interface type\n");
567 goto err1;
568 }
569
570 switch (pdata->ch[i].chan) {
571 case LCDC_CHAN_MAINLCD:
572 priv->ch[j].enabled = 1 << 1;
573 priv->ch[j].reg_offs = lcdc_offs_mainlcd;
574 j++;
575 break;
576 case LCDC_CHAN_SUBLCD:
577 priv->ch[j].enabled = 1 << 2;
578 priv->ch[j].reg_offs = lcdc_offs_sublcd;
579 j++;
580 break;
581 }
582 }
583
584 if (!j) {
585 dev_err(&pdev->dev, "no channels defined\n");
586 error = -EINVAL;
587 goto err1;
588 }
589
590 error = sh_mobile_lcdc_setup_clocks(&pdev->dev,
591 pdata->clock_source, priv);
592 if (error) {
593 dev_err(&pdev->dev, "unable to setup clocks\n");
594 goto err1;
595 }
596
597 priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
598
599 for (i = 0; i < j; i++) {
600 info = &priv->ch[i].info;
601 cfg = &priv->ch[i].cfg;
602
603 info->fbops = &sh_mobile_lcdc_ops;
604 info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
605 info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
606 info->var.width = cfg->lcd_size_cfg.width;
607 info->var.height = cfg->lcd_size_cfg.height;
608 info->var.activate = FB_ACTIVATE_NOW;
609 error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
610 if (error)
611 break;
612
613 info->fix = sh_mobile_lcdc_fix;
614 info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
615 info->fix.smem_len = info->fix.line_length * cfg->lcd_cfg.yres;
616
617 buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
618 &priv->ch[i].dma_handle, GFP_KERNEL);
619 if (!buf) {
620 dev_err(&pdev->dev, "unable to allocate buffer\n");
621 error = -ENOMEM;
622 break;
623 }
624
625 info->pseudo_palette = &priv->ch[i].pseudo_palette;
626 info->flags = FBINFO_FLAG_DEFAULT;
627
628 error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
629 if (error < 0) {
630 dev_err(&pdev->dev, "unable to allocate cmap\n");
631 dma_free_coherent(&pdev->dev, info->fix.smem_len,
632 buf, priv->ch[i].dma_handle);
633 break;
634 }
635
636 memset(buf, 0, info->fix.smem_len);
637 info->fix.smem_start = priv->ch[i].dma_handle;
638 info->screen_base = buf;
639 info->device = &pdev->dev;
640 }
641
642 if (error)
643 goto err1;
644
645 error = sh_mobile_lcdc_start(priv);
646 if (error) {
647 dev_err(&pdev->dev, "unable to start hardware\n");
648 goto err1;
649 }
650
651 for (i = 0; i < j; i++) {
652 error = register_framebuffer(&priv->ch[i].info);
653 if (error < 0)
654 goto err1;
655 }
656
657 for (i = 0; i < j; i++) {
658 info = &priv->ch[i].info;
659 dev_info(info->dev,
660 "registered %s/%s as %dx%d %dbpp.\n",
661 pdev->name,
662 (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
663 "mainlcd" : "sublcd",
664 (int) priv->ch[i].cfg.lcd_cfg.xres,
665 (int) priv->ch[i].cfg.lcd_cfg.yres,
666 priv->ch[i].cfg.bpp);
667 }
668
669 return 0;
670 err1:
671 sh_mobile_lcdc_remove(pdev);
672 err0:
673 return error;
674}
675
676static int sh_mobile_lcdc_remove(struct platform_device *pdev)
677{
678 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
679 struct fb_info *info;
680 int i;
681
682 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
683 if (priv->ch[i].info.dev)
684 unregister_framebuffer(&priv->ch[i].info);
685
686 sh_mobile_lcdc_stop(priv);
687
688 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
689 info = &priv->ch[i].info;
690
691 if (!info->device)
692 continue;
693
694 dma_free_coherent(&pdev->dev, info->fix.smem_len,
695 info->screen_base, priv->ch[i].dma_handle);
696 fb_dealloc_cmap(&info->cmap);
697 }
698
699#ifdef CONFIG_HAVE_CLK
700 if (priv->clk) {
701 clk_disable(priv->clk);
702 clk_put(priv->clk);
703 }
704#endif
705
706 if (priv->base)
707 iounmap(priv->base);
708
709 kfree(priv);
710 return 0;
711}
712
713static struct platform_driver sh_mobile_lcdc_driver = {
714 .driver = {
715 .name = "sh_mobile_lcdc_fb",
716 .owner = THIS_MODULE,
717 },
718 .probe = sh_mobile_lcdc_probe,
719 .remove = sh_mobile_lcdc_remove,
720};
721
722static int __init sh_mobile_lcdc_init(void)
723{
724 return platform_driver_register(&sh_mobile_lcdc_driver);
725}
726
727static void __exit sh_mobile_lcdc_exit(void)
728{
729 platform_driver_unregister(&sh_mobile_lcdc_driver);
730}
731
732module_init(sh_mobile_lcdc_init);
733module_exit(sh_mobile_lcdc_exit);
734
735MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
736MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
737MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index f40a680df86f..b96005c39c67 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -73,7 +73,6 @@
73#ifdef SIS_CP 73#ifdef SIS_CP
74#undef SIS_CP 74#undef SIS_CP
75#endif 75#endif
76#include <linux/version.h>
77#include <linux/types.h> 76#include <linux/types.h>
78#include <asm/io.h> 77#include <asm/io.h>
79#include <linux/fb.h> 78#include <linux/fb.h>
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index 7708e1e1d99e..51d99222375d 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -67,7 +67,6 @@
67#ifdef SIS_CP 67#ifdef SIS_CP
68#undef SIS_CP 68#undef SIS_CP
69#endif 69#endif
70#include <linux/version.h>
71#include <linux/types.h> 70#include <linux/types.h>
72#include <asm/io.h> 71#include <asm/io.h>
73#include <linux/fb.h> 72#include <linux/fb.h>
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index 47a33501549d..99c04a4855d1 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -30,7 +30,6 @@
30#include "vgatypes.h" 30#include "vgatypes.h"
31#include "vstruct.h" 31#include "vstruct.h"
32 32
33#include <linux/version.h>
34#include <linux/types.h> 33#include <linux/types.h>
35#include <linux/fb.h> 34#include <linux/fb.h>
36 35
diff --git a/drivers/video/sis/osdef.h b/drivers/video/sis/osdef.h
index c1492782cb18..6ff8f988a1a7 100644
--- a/drivers/video/sis/osdef.h
+++ b/drivers/video/sis/osdef.h
@@ -87,7 +87,6 @@
87/**********************************************************************/ 87/**********************************************************************/
88 88
89#ifdef SIS_LINUX_KERNEL 89#ifdef SIS_LINUX_KERNEL
90#include <linux/version.h>
91 90
92#ifdef CONFIG_FB_SIS_300 91#ifdef CONFIG_FB_SIS_300
93#define SIS300 92#define SIS300
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index a14e82211037..7c5710e3fb56 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -24,8 +24,6 @@
24#ifndef _SIS_H_ 24#ifndef _SIS_H_
25#define _SIS_H_ 25#define _SIS_H_
26 26
27#include <linux/version.h>
28
29#include "osdef.h" 27#include "osdef.h"
30#include <video/sisfb.h> 28#include <video/sisfb.h>
31 29
@@ -42,16 +40,6 @@
42#define SIS_NEW_CONFIG_COMPAT 40#define SIS_NEW_CONFIG_COMPAT
43#endif /* CONFIG_COMPAT */ 41#endif /* CONFIG_COMPAT */
44 42
45#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
46#define SIS_IOTYPE1 void __iomem
47#define SIS_IOTYPE2 __iomem
48#define SISINITSTATIC static
49#else
50#define SIS_IOTYPE1 unsigned char
51#define SIS_IOTYPE2
52#define SISINITSTATIC
53#endif
54
55#undef SISFBDEBUG 43#undef SISFBDEBUG
56 44
57#ifdef SISFBDEBUG 45#ifdef SISFBDEBUG
@@ -505,8 +493,8 @@ struct sis_video_info {
505 493
506 unsigned long UMAsize, LFBsize; 494 unsigned long UMAsize, LFBsize;
507 495
508 SIS_IOTYPE1 *video_vbase; 496 void __iomem *video_vbase;
509 SIS_IOTYPE1 *mmio_vbase; 497 void __iomem *mmio_vbase;
510 498
511 unsigned char *bios_abase; 499 unsigned char *bios_abase;
512 500
@@ -533,8 +521,8 @@ struct sis_video_info {
533 int sisfb_nocrt2rate; 521 int sisfb_nocrt2rate;
534 522
535 u32 heapstart; /* offset */ 523 u32 heapstart; /* offset */
536 SIS_IOTYPE1 *sisfb_heap_start; /* address */ 524 void __iomem *sisfb_heap_start; /* address */
537 SIS_IOTYPE1 *sisfb_heap_end; /* address */ 525 void __iomem *sisfb_heap_end; /* address */
538 u32 sisfb_heap_size; 526 u32 sisfb_heap_size;
539 int havenoheap; 527 int havenoheap;
540 528
@@ -612,7 +600,7 @@ struct sis_video_info {
612 u8 detectedpdca; 600 u8 detectedpdca;
613 u8 detectedlcda; 601 u8 detectedlcda;
614 602
615 SIS_IOTYPE1 *hwcursor_vbase; 603 void __iomem *hwcursor_vbase;
616 604
617 int chronteltype; 605 int chronteltype;
618 int tvxpos, tvypos; 606 int tvxpos, tvypos;
diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/sis/sis_accel.c
index 7addf91d2fea..ceb434c95c0d 100644
--- a/drivers/video/sis/sis_accel.c
+++ b/drivers/video/sis/sis_accel.c
@@ -28,7 +28,6 @@
28 * for more information and updates) 28 * for more information and updates)
29 */ 29 */
30 30
31#include <linux/version.h>
32#include <linux/module.h> 31#include <linux/module.h>
33#include <linux/kernel.h> 32#include <linux/kernel.h>
34#include <linux/fb.h> 33#include <linux/fb.h>
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index b9343844cd1f..346d6458cf76 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -33,7 +33,6 @@
33 * 33 *
34 */ 34 */
35 35
36#include <linux/version.h>
37#include <linux/module.h> 36#include <linux/module.h>
38#include <linux/moduleparam.h> 37#include <linux/moduleparam.h>
39#include <linux/kernel.h> 38#include <linux/kernel.h>
@@ -41,13 +40,7 @@
41#include <linux/errno.h> 40#include <linux/errno.h>
42#include <linux/string.h> 41#include <linux/string.h>
43#include <linux/mm.h> 42#include <linux/mm.h>
44
45#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
46#include <linux/tty.h>
47#else
48#include <linux/screen_info.h> 43#include <linux/screen_info.h>
49#endif
50
51#include <linux/slab.h> 44#include <linux/slab.h>
52#include <linux/fb.h> 45#include <linux/fb.h>
53#include <linux/selection.h> 46#include <linux/selection.h>
@@ -1167,11 +1160,7 @@ sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1167 unsigned short modeno = ivideo->mode_no; 1160 unsigned short modeno = ivideo->mode_no;
1168 1161
1169 /* >=2.6.12's fbcon clears the screen anyway */ 1162 /* >=2.6.12's fbcon clears the screen anyway */
1170#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
1171 if(!clrscrn) modeno |= 0x80;
1172#else
1173 modeno |= 0x80; 1163 modeno |= 0x80;
1174#endif
1175 1164
1176 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); 1165 outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1177 1166
@@ -1436,11 +1425,8 @@ sisfb_set_par(struct fb_info *info)
1436 if((err = sisfb_do_set_var(&info->var, 1, info))) 1425 if((err = sisfb_do_set_var(&info->var, 1, info)))
1437 return err; 1426 return err;
1438 1427
1439#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
1440 sisfb_get_fix(&info->fix, info->currcon, info);
1441#else
1442 sisfb_get_fix(&info->fix, -1, info); 1428 sisfb_get_fix(&info->fix, -1, info);
1443#endif 1429
1444 return 0; 1430 return 0;
1445} 1431}
1446 1432
@@ -1676,14 +1662,8 @@ sisfb_blank(int blank, struct fb_info *info)
1676 1662
1677/* ----------- FBDev related routines for all series ---------- */ 1663/* ----------- FBDev related routines for all series ---------- */
1678 1664
1679#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
1680static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, 1665static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1681 unsigned long arg) 1666 unsigned long arg)
1682#else
1683static int sisfb_ioctl(struct inode *inode, struct file *file,
1684 unsigned int cmd, unsigned long arg,
1685 struct fb_info *info)
1686#endif
1687{ 1667{
1688 struct sis_video_info *ivideo = (struct sis_video_info *)info->par; 1668 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1689 struct sis_memreq sismemreq; 1669 struct sis_memreq sismemreq;
@@ -3986,8 +3966,7 @@ sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_comm
3986} 3966}
3987 3967
3988#ifndef MODULE 3968#ifndef MODULE
3989SISINITSTATIC int __init 3969static int __init sisfb_setup(char *options)
3990sisfb_setup(char *options)
3991{ 3970{
3992 char *this_opt; 3971 char *this_opt;
3993 3972
@@ -4086,9 +4065,9 @@ sisfb_setup(char *options)
4086#endif 4065#endif
4087 4066
4088static int __devinit 4067static int __devinit
4089sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo) 4068sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
4090{ 4069{
4091 SIS_IOTYPE1 *rom; 4070 void __iomem *rom;
4092 int romptr; 4071 int romptr;
4093 4072
4094 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) 4073 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
@@ -4117,10 +4096,9 @@ static unsigned char * __devinit
4117sisfb_find_rom(struct pci_dev *pdev) 4096sisfb_find_rom(struct pci_dev *pdev)
4118{ 4097{
4119 struct sis_video_info *ivideo = pci_get_drvdata(pdev); 4098 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4120 SIS_IOTYPE1 *rom_base; 4099 void __iomem *rom_base;
4121 unsigned char *myrombase = NULL; 4100 unsigned char *myrombase = NULL;
4122 u32 temp; 4101 u32 temp;
4123#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
4124 size_t romsize; 4102 size_t romsize;
4125 4103
4126 /* First, try the official pci ROM functions (except 4104 /* First, try the official pci ROM functions (except
@@ -4151,7 +4129,6 @@ sisfb_find_rom(struct pci_dev *pdev)
4151 } 4129 }
4152 4130
4153 if(myrombase) return myrombase; 4131 if(myrombase) return myrombase;
4154#endif
4155 4132
4156 /* Otherwise do it the conventional way. */ 4133 /* Otherwise do it the conventional way. */
4157 4134
@@ -4225,7 +4202,7 @@ sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
4225static int __devinit 4202static int __devinit
4226sisfb_post_300_buswidth(struct sis_video_info *ivideo) 4203sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4227{ 4204{
4228 SIS_IOTYPE1 *FBAddress = ivideo->video_vbase; 4205 void __iomem *FBAddress = ivideo->video_vbase;
4229 unsigned short temp; 4206 unsigned short temp;
4230 unsigned char reg; 4207 unsigned char reg;
4231 int i, j; 4208 int i, j;
@@ -4273,7 +4250,7 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
4273 int PseudoRankCapacity, int PseudoAdrPinCount, 4250 int PseudoRankCapacity, int PseudoAdrPinCount,
4274 unsigned int mapsize) 4251 unsigned int mapsize)
4275{ 4252{
4276 SIS_IOTYPE1 *FBAddr = ivideo->video_vbase; 4253 void __iomem *FBAddr = ivideo->video_vbase;
4277 unsigned short sr14; 4254 unsigned short sr14;
4278 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid; 4255 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4279 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage; 4256 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
@@ -5829,7 +5806,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5829 ivideo->engineok = 0; 5806 ivideo->engineok = 0;
5830 5807
5831 ivideo->sisfb_was_boot_device = 0; 5808 ivideo->sisfb_was_boot_device = 0;
5832#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)) 5809
5833 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) { 5810 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5834 if(ivideo->sisvga_enabled) 5811 if(ivideo->sisvga_enabled)
5835 ivideo->sisfb_was_boot_device = 1; 5812 ivideo->sisfb_was_boot_device = 1;
@@ -5840,7 +5817,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5840 "as the primary VGA device\n"); 5817 "as the primary VGA device\n");
5841 } 5818 }
5842 } 5819 }
5843#endif
5844 5820
5845 ivideo->sisfb_parm_mem = sisfb_parm_mem; 5821 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5846 ivideo->sisfb_accel = sisfb_accel; 5822 ivideo->sisfb_accel = sisfb_accel;
@@ -6010,7 +5986,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
6010 ivideo->modeprechange = reg & 0x7f; 5986 ivideo->modeprechange = reg & 0x7f;
6011 } else if(ivideo->sisvga_enabled) { 5987 } else if(ivideo->sisvga_enabled) {
6012#if defined(__i386__) || defined(__x86_64__) 5988#if defined(__i386__) || defined(__x86_64__)
6013 unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100); 5989 unsigned char __iomem *tt = ioremap(0x400, 0x100);
6014 if(tt) { 5990 if(tt) {
6015 ivideo->modeprechange = readb(tt + 0x49); 5991 ivideo->modeprechange = readb(tt + 0x49);
6016 iounmap(tt); 5992 iounmap(tt);
@@ -6503,7 +6479,7 @@ static struct pci_driver sisfb_driver = {
6503 .remove = __devexit_p(sisfb_remove) 6479 .remove = __devexit_p(sisfb_remove)
6504}; 6480};
6505 6481
6506SISINITSTATIC int __init sisfb_init(void) 6482static int __init sisfb_init(void)
6507{ 6483{
6508#ifndef MODULE 6484#ifndef MODULE
6509 char *options = NULL; 6485 char *options = NULL;
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 3e3b7fa05d6c..9540e977270e 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -665,11 +665,11 @@ static struct _customttable {
665 665
666/* Interface used by the world */ 666/* Interface used by the world */
667#ifndef MODULE 667#ifndef MODULE
668SISINITSTATIC int sisfb_setup(char *options); 668static int sisfb_setup(char *options);
669#endif 669#endif
670 670
671/* Interface to the low level console driver */ 671/* Interface to the low level console driver */
672SISINITSTATIC int sisfb_init(void); 672static int sisfb_init(void);
673 673
674/* fbdev routines */ 674/* fbdev routines */
675static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, 675static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index b532fbd2b04c..81a22eaabfde 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -53,10 +53,6 @@
53#ifndef _VGATYPES_H_ 53#ifndef _VGATYPES_H_
54#define _VGATYPES_H_ 54#define _VGATYPES_H_
55 55
56#ifdef SIS_LINUX_KERNEL
57#include <linux/version.h>
58#endif
59
60#define SISIOMEMTYPE 56#define SISIOMEMTYPE
61 57
62#ifdef SIS_LINUX_KERNEL 58#ifdef SIS_LINUX_KERNEL
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 62321458f71a..df5336561d13 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -675,13 +675,13 @@ static struct fb_ops xxxfb_ops = {
675 * Initialization 675 * Initialization
676 */ 676 */
677 677
678/* static int __init xxfb_probe (struct device *device) -- for platform devs */ 678/* static int __init xxfb_probe (struct platform_device *pdev) -- for platform devs */
679static int __devinit xxxfb_probe(struct pci_dev *dev, 679static int __devinit xxxfb_probe(struct pci_dev *dev,
680 const struct pci_device_id *ent) 680 const struct pci_device_id *ent)
681{ 681{
682 struct fb_info *info; 682 struct fb_info *info;
683 struct xxx_par *par; 683 struct xxx_par *par;
684 struct device* device = &dev->dev; /* for pci drivers */ 684 struct device *device = &dev->dev; /* or &pdev->dev */
685 int cmap_len, retval; 685 int cmap_len, retval;
686 686
687 /* 687 /*
@@ -824,18 +824,18 @@ static int __devinit xxxfb_probe(struct pci_dev *dev,
824 return -EINVAL; 824 return -EINVAL;
825 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, 825 printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
826 info->fix.id); 826 info->fix.id);
827 pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */ 827 pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */
828 return 0; 828 return 0;
829} 829}
830 830
831 /* 831 /*
832 * Cleanup 832 * Cleanup
833 */ 833 */
834/* static void __devexit xxxfb_remove(struct device *device) */ 834/* static void __devexit xxxfb_remove(struct platform_device *pdev) */
835static void __devexit xxxfb_remove(struct pci_dev *dev) 835static void __devexit xxxfb_remove(struct pci_dev *dev)
836{ 836{
837 struct fb_info *info = pci_get_drvdata(dev); 837 struct fb_info *info = pci_get_drvdata(dev);
838 /* or dev_get_drvdata(device); */ 838 /* or platform_get_drvdata(pdev); */
839 839
840 if (info) { 840 if (info) {
841 unregister_framebuffer(info); 841 unregister_framebuffer(info);
@@ -961,18 +961,17 @@ static int xxxfb_resume(struct platform_dev *dev)
961#define xxxfb_resume NULL 961#define xxxfb_resume NULL
962#endif /* CONFIG_PM */ 962#endif /* CONFIG_PM */
963 963
964static struct device_driver xxxfb_driver = { 964static struct platform_device_driver xxxfb_driver = {
965 .name = "xxxfb",
966 .bus = &platform_bus_type,
967 .probe = xxxfb_probe, 965 .probe = xxxfb_probe,
968 .remove = xxxfb_remove, 966 .remove = xxxfb_remove,
969 .suspend = xxxfb_suspend, /* optional but recommended */ 967 .suspend = xxxfb_suspend, /* optional but recommended */
970 .resume = xxxfb_resume, /* optional but recommended */ 968 .resume = xxxfb_resume, /* optional but recommended */
969 .driver = {
970 .name = "xxxfb",
971 },
971}; 972};
972 973
973static struct platform_device xxxfb_device = { 974static struct platform_device *xxxfb_device;
974 .name = "xxxfb",
975};
976 975
977#ifndef MODULE 976#ifndef MODULE
978 /* 977 /*
@@ -1002,12 +1001,16 @@ static int __init xxxfb_init(void)
1002 return -ENODEV; 1001 return -ENODEV;
1003 xxxfb_setup(option); 1002 xxxfb_setup(option);
1004#endif 1003#endif
1005 ret = driver_register(&xxxfb_driver); 1004 ret = platform_driver_register(&xxxfb_driver);
1006 1005
1007 if (!ret) { 1006 if (!ret) {
1008 ret = platform_device_register(&xxxfb_device); 1007 xxxfb_device = platform_device_register_simple("xxxfb", 0,
1009 if (ret) 1008 NULL, 0);
1010 driver_unregister(&xxxfb_driver); 1009
1010 if (IS_ERR(xxxfb_device)) {
1011 platform_driver_unregister(&xxxfb_driver);
1012 ret = PTR_ERR(xxxfb_device);
1013 }
1011 } 1014 }
1012 1015
1013 return ret; 1016 return ret;
@@ -1015,8 +1018,8 @@ static int __init xxxfb_init(void)
1015 1018
1016static void __exit xxxfb_exit(void) 1019static void __exit xxxfb_exit(void)
1017{ 1020{
1018 platform_device_unregister(&xxxfb_device); 1021 platform_device_unregister(xxxfb_device);
1019 driver_unregister(&xxxfb_driver); 1022 platform_driver_unregister(&xxxfb_driver);
1020} 1023}
1021#endif /* CONFIG_PCI */ 1024#endif /* CONFIG_PCI */
1022 1025
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 15d4a768b1f6..f94ae84a58cd 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -48,10 +48,15 @@ enum sm501_controller {
48 HEAD_PANEL = 1, 48 HEAD_PANEL = 1,
49}; 49};
50 50
51/* SM501 memory address */ 51/* SM501 memory address.
52 *
53 * This structure is used to track memory usage within the SM501 framebuffer
54 * allocation. The sm_addr field is stored as an offset as it is often used
55 * against both the physical and mapped addresses.
56 */
52struct sm501_mem { 57struct sm501_mem {
53 unsigned long size; 58 unsigned long size;
54 unsigned long sm_addr; 59 unsigned long sm_addr; /* offset from base of sm501 fb. */
55 void __iomem *k_addr; 60 void __iomem *k_addr;
56}; 61};
57 62
@@ -142,31 +147,68 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
142static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, 147static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
143 unsigned int why, size_t size) 148 unsigned int why, size_t size)
144{ 149{
145 unsigned int ptr = 0; 150 struct sm501fb_par *par;
151 struct fb_info *fbi;
152 unsigned int ptr;
153 unsigned int end;
146 154
147 switch (why) { 155 switch (why) {
148 case SM501_MEMF_CURSOR: 156 case SM501_MEMF_CURSOR:
149 ptr = inf->fbmem_len - size; 157 ptr = inf->fbmem_len - size;
150 inf->fbmem_len = ptr; 158 inf->fbmem_len = ptr; /* adjust available memory. */
151 break; 159 break;
152 160
153 case SM501_MEMF_PANEL: 161 case SM501_MEMF_PANEL:
154 ptr = inf->fbmem_len - size; 162 ptr = inf->fbmem_len - size;
155 if (ptr < inf->fb[0]->fix.smem_len) 163 fbi = inf->fb[HEAD_CRT];
164
165 /* round down, some programs such as directfb do not draw
166 * 0,0 correctly unless the start is aligned to a page start.
167 */
168
169 if (ptr > 0)
170 ptr &= ~(PAGE_SIZE - 1);
171
172 if (fbi && ptr < fbi->fix.smem_len)
173 return -ENOMEM;
174
175 if (ptr < 0)
156 return -ENOMEM; 176 return -ENOMEM;
157 177
158 break; 178 break;
159 179
160 case SM501_MEMF_CRT: 180 case SM501_MEMF_CRT:
161 ptr = 0; 181 ptr = 0;
182
183 /* check to see if we have panel memory allocated
184 * which would put an limit on available memory. */
185
186 fbi = inf->fb[HEAD_PANEL];
187 if (fbi) {
188 par = fbi->par;
189 end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len;
190 } else
191 end = inf->fbmem_len;
192
193 if ((ptr + size) > end)
194 return -ENOMEM;
195
162 break; 196 break;
163 197
164 case SM501_MEMF_ACCEL: 198 case SM501_MEMF_ACCEL:
165 ptr = inf->fb[0]->fix.smem_len; 199 fbi = inf->fb[HEAD_CRT];
200 ptr = fbi ? fbi->fix.smem_len : 0;
201
202 fbi = inf->fb[HEAD_PANEL];
203 if (fbi) {
204 par = fbi->par;
205 end = par->screen.sm_addr;
206 } else
207 end = inf->fbmem_len;
166 208
167 if ((ptr + size) > 209 if ((ptr + size) > end)
168 (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
169 return -ENOMEM; 210 return -ENOMEM;
211
170 break; 212 break;
171 213
172 default: 214 default:
@@ -663,15 +705,25 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
663 sm501fb_sync_regs(fbi); 705 sm501fb_sync_regs(fbi);
664 mdelay(10); 706 mdelay(10);
665 707
708 /* VBIASEN */
709
666 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { 710 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
667 control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ 711 if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
712 control &= ~SM501_DC_PANEL_CONTROL_BIAS;
713 else
714 control |= SM501_DC_PANEL_CONTROL_BIAS;
715
668 writel(control, ctrl_reg); 716 writel(control, ctrl_reg);
669 sm501fb_sync_regs(fbi); 717 sm501fb_sync_regs(fbi);
670 mdelay(10); 718 mdelay(10);
671 } 719 }
672 720
673 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { 721 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
674 control |= SM501_DC_PANEL_CONTROL_FPEN; 722 if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
723 control &= ~SM501_DC_PANEL_CONTROL_FPEN;
724 else
725 control |= SM501_DC_PANEL_CONTROL_FPEN;
726
675 writel(control, ctrl_reg); 727 writel(control, ctrl_reg);
676 sm501fb_sync_regs(fbi); 728 sm501fb_sync_regs(fbi);
677 mdelay(10); 729 mdelay(10);
@@ -679,14 +731,22 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
679 } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { 731 } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
680 /* disable panel power */ 732 /* disable panel power */
681 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { 733 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
682 control &= ~SM501_DC_PANEL_CONTROL_FPEN; 734 if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
735 control |= SM501_DC_PANEL_CONTROL_FPEN;
736 else
737 control &= ~SM501_DC_PANEL_CONTROL_FPEN;
738
683 writel(control, ctrl_reg); 739 writel(control, ctrl_reg);
684 sm501fb_sync_regs(fbi); 740 sm501fb_sync_regs(fbi);
685 mdelay(10); 741 mdelay(10);
686 } 742 }
687 743
688 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { 744 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
689 control &= ~SM501_DC_PANEL_CONTROL_BIAS; 745 if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
746 control |= SM501_DC_PANEL_CONTROL_BIAS;
747 else
748 control &= ~SM501_DC_PANEL_CONTROL_BIAS;
749
690 writel(control, ctrl_reg); 750 writel(control, ctrl_reg);
691 sm501fb_sync_regs(fbi); 751 sm501fb_sync_regs(fbi);
692 mdelay(10); 752 mdelay(10);
@@ -1210,39 +1270,6 @@ static struct fb_ops sm501fb_ops_pnl = {
1210 .fb_imageblit = cfb_imageblit, 1270 .fb_imageblit = cfb_imageblit,
1211}; 1271};
1212 1272
1213/* sm501fb_info_alloc
1214 *
1215 * creates and initialises an sm501fb_info structure
1216*/
1217
1218static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
1219 struct fb_info *fbinfo_pnl)
1220{
1221 struct sm501fb_info *info;
1222 struct sm501fb_par *par;
1223
1224 info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
1225 if (info) {
1226 /* set the references back */
1227
1228 par = fbinfo_crt->par;
1229 par->info = info;
1230 par->head = HEAD_CRT;
1231 fbinfo_crt->pseudo_palette = &par->pseudo_palette;
1232
1233 par = fbinfo_pnl->par;
1234 par->info = info;
1235 par->head = HEAD_PANEL;
1236 fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
1237
1238 /* store the two fbs into our info */
1239 info->fb[HEAD_CRT] = fbinfo_crt;
1240 info->fb[HEAD_PANEL] = fbinfo_pnl;
1241 }
1242
1243 return info;
1244}
1245
1246/* sm501_init_cursor 1273/* sm501_init_cursor
1247 * 1274 *
1248 * initialise hw cursor parameters 1275 * initialise hw cursor parameters
@@ -1250,10 +1277,16 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
1250 1277
1251static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) 1278static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
1252{ 1279{
1253 struct sm501fb_par *par = fbi->par; 1280 struct sm501fb_par *par;
1254 struct sm501fb_info *info = par->info; 1281 struct sm501fb_info *info;
1255 int ret; 1282 int ret;
1256 1283
1284 if (fbi == NULL)
1285 return 0;
1286
1287 par = fbi->par;
1288 info = par->info;
1289
1257 par->cursor_regs = info->regs + reg_base; 1290 par->cursor_regs = info->regs + reg_base;
1258 1291
1259 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); 1292 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
@@ -1281,13 +1314,10 @@ static int sm501fb_start(struct sm501fb_info *info,
1281 struct platform_device *pdev) 1314 struct platform_device *pdev)
1282{ 1315{
1283 struct resource *res; 1316 struct resource *res;
1284 struct device *dev; 1317 struct device *dev = &pdev->dev;
1285 int k; 1318 int k;
1286 int ret; 1319 int ret;
1287 1320
1288 info->dev = dev = &pdev->dev;
1289 platform_set_drvdata(pdev, info);
1290
1291 info->irq = ret = platform_get_irq(pdev, 0); 1321 info->irq = ret = platform_get_irq(pdev, 0);
1292 if (ret < 0) { 1322 if (ret < 0) {
1293 /* we currently do not use the IRQ */ 1323 /* we currently do not use the IRQ */
@@ -1390,11 +1420,6 @@ static void sm501fb_stop(struct sm501fb_info *info)
1390 kfree(info->regs_res); 1420 kfree(info->regs_res);
1391} 1421}
1392 1422
1393static void sm501fb_info_release(struct sm501fb_info *info)
1394{
1395 kfree(info);
1396}
1397
1398static int sm501fb_init_fb(struct fb_info *fb, 1423static int sm501fb_init_fb(struct fb_info *fb,
1399 enum sm501_controller head, 1424 enum sm501_controller head,
1400 const char *fbname) 1425 const char *fbname)
@@ -1539,36 +1564,93 @@ static struct sm501_platdata_fb sm501fb_def_pdata = {
1539static char driver_name_crt[] = "sm501fb-crt"; 1564static char driver_name_crt[] = "sm501fb-crt";
1540static char driver_name_pnl[] = "sm501fb-panel"; 1565static char driver_name_pnl[] = "sm501fb-panel";
1541 1566
1542static int __init sm501fb_probe(struct platform_device *pdev) 1567static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
1568 enum sm501_controller head)
1543{ 1569{
1544 struct sm501fb_info *info; 1570 unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
1545 struct device *dev = &pdev->dev; 1571 struct sm501_platdata_fbsub *pd;
1546 struct fb_info *fbinfo_crt; 1572 struct sm501fb_par *par;
1547 struct fb_info *fbinfo_pnl; 1573 struct fb_info *fbi;
1548 int ret;
1549 1574
1550 /* allocate our framebuffers */ 1575 pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
1576
1577 /* Do not initialise if we've not been given any platform data */
1578 if (pd == NULL) {
1579 dev_info(info->dev, "no data for fb %s (disabled)\n", name);
1580 return 0;
1581 }
1551 1582
1552 fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev); 1583 fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
1553 if (fbinfo_crt == NULL) { 1584 if (fbi == NULL) {
1554 dev_err(dev, "cannot allocate crt framebuffer\n"); 1585 dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
1555 return -ENOMEM; 1586 return -ENOMEM;
1556 } 1587 }
1557 1588
1558 fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev); 1589 par = fbi->par;
1559 if (fbinfo_pnl == NULL) { 1590 par->info = info;
1560 dev_err(dev, "cannot allocate panel framebuffer\n"); 1591 par->head = head;
1561 ret = -ENOMEM; 1592 fbi->pseudo_palette = &par->pseudo_palette;
1562 goto fbinfo_crt_alloc_fail; 1593
1594 info->fb[head] = fbi;
1595
1596 return 0;
1597}
1598
1599/* Free up anything allocated by sm501fb_init_fb */
1600
1601static void sm501_free_init_fb(struct sm501fb_info *info,
1602 enum sm501_controller head)
1603{
1604 struct fb_info *fbi = info->fb[head];
1605
1606 fb_dealloc_cmap(&fbi->cmap);
1607}
1608
1609static int __devinit sm501fb_start_one(struct sm501fb_info *info,
1610 enum sm501_controller head,
1611 const char *drvname)
1612{
1613 struct fb_info *fbi = info->fb[head];
1614 int ret;
1615
1616 if (!fbi)
1617 return 0;
1618
1619 ret = sm501fb_init_fb(info->fb[head], head, drvname);
1620 if (ret) {
1621 dev_err(info->dev, "cannot initialise fb %s\n", drvname);
1622 return ret;
1623 }
1624
1625 ret = register_framebuffer(info->fb[head]);
1626 if (ret) {
1627 dev_err(info->dev, "failed to register fb %s\n", drvname);
1628 sm501_free_init_fb(info, head);
1629 return ret;
1563 } 1630 }
1564 1631
1565 info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl); 1632 dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
1566 if (info == NULL) { 1633
1567 dev_err(dev, "cannot allocate par\n"); 1634 return 0;
1568 ret = -ENOMEM; 1635}
1569 goto sm501fb_alloc_fail; 1636
1637static int __devinit sm501fb_probe(struct platform_device *pdev)
1638{
1639 struct sm501fb_info *info;
1640 struct device *dev = &pdev->dev;
1641 int ret;
1642
1643 /* allocate our framebuffers */
1644
1645 info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
1646 if (!info) {
1647 dev_err(dev, "failed to allocate state\n");
1648 return -ENOMEM;
1570 } 1649 }
1571 1650
1651 info->dev = dev = &pdev->dev;
1652 platform_set_drvdata(pdev, info);
1653
1572 if (dev->parent->platform_data) { 1654 if (dev->parent->platform_data) {
1573 struct sm501_platdata *pd = dev->parent->platform_data; 1655 struct sm501_platdata *pd = dev->parent->platform_data;
1574 info->pdata = pd->fb; 1656 info->pdata = pd->fb;
@@ -1579,90 +1661,88 @@ static int __init sm501fb_probe(struct platform_device *pdev)
1579 info->pdata = &sm501fb_def_pdata; 1661 info->pdata = &sm501fb_def_pdata;
1580 } 1662 }
1581 1663
1582 /* start the framebuffers */ 1664 /* probe for the presence of each panel */
1583 1665
1584 ret = sm501fb_start(info, pdev); 1666 ret = sm501fb_probe_one(info, HEAD_CRT);
1585 if (ret) { 1667 if (ret < 0) {
1586 dev_err(dev, "cannot initialise SM501\n"); 1668 dev_err(dev, "failed to probe CRT\n");
1587 goto sm501fb_start_fail; 1669 goto err_alloc;
1588 } 1670 }
1589 1671
1590 /* CRT framebuffer setup */ 1672 ret = sm501fb_probe_one(info, HEAD_PANEL);
1673 if (ret < 0) {
1674 dev_err(dev, "failed to probe PANEL\n");
1675 goto err_probed_crt;
1676 }
1591 1677
1592 ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt); 1678 if (info->fb[HEAD_PANEL] == NULL &&
1593 if (ret) { 1679 info->fb[HEAD_CRT] == NULL) {
1594 dev_err(dev, "cannot initialise CRT fb\n"); 1680 dev_err(dev, "no framebuffers found\n");
1595 goto sm501fb_start_fail; 1681 goto err_alloc;
1596 } 1682 }
1597 1683
1598 /* Panel framebuffer setup */ 1684 /* get the resources for both of the framebuffers */
1599 1685
1600 ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl); 1686 ret = sm501fb_start(info, pdev);
1601 if (ret) { 1687 if (ret) {
1602 dev_err(dev, "cannot initialise Panel fb\n"); 1688 dev_err(dev, "cannot initialise SM501\n");
1603 goto sm501fb_start_fail; 1689 goto err_probed_panel;
1604 } 1690 }
1605 1691
1606 /* register framebuffers */ 1692 ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
1607 1693 if (ret) {
1608 ret = register_framebuffer(fbinfo_crt); 1694 dev_err(dev, "failed to start CRT\n");
1609 if (ret < 0) { 1695 goto err_started;
1610 dev_err(dev, "failed to register CRT fb (%d)\n", ret);
1611 goto register_crt_fail;
1612 } 1696 }
1613 1697
1614 ret = register_framebuffer(fbinfo_pnl); 1698 ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
1615 if (ret < 0) { 1699 if (ret) {
1616 dev_err(dev, "failed to register panel fb (%d)\n", ret); 1700 dev_err(dev, "failed to start Panel\n");
1617 goto register_pnl_fail; 1701 goto err_started_crt;
1618 } 1702 }
1619 1703
1620 dev_info(dev, "fb%d: %s frame buffer device\n",
1621 fbinfo_crt->node, fbinfo_crt->fix.id);
1622
1623 dev_info(dev, "fb%d: %s frame buffer device\n",
1624 fbinfo_pnl->node, fbinfo_pnl->fix.id);
1625
1626 /* create device files */ 1704 /* create device files */
1627 1705
1628 ret = device_create_file(dev, &dev_attr_crt_src); 1706 ret = device_create_file(dev, &dev_attr_crt_src);
1629 if (ret) 1707 if (ret)
1630 goto crtsrc_fail; 1708 goto err_started_panel;
1631 1709
1632 ret = device_create_file(dev, &dev_attr_fbregs_pnl); 1710 ret = device_create_file(dev, &dev_attr_fbregs_pnl);
1633 if (ret) 1711 if (ret)
1634 goto fbregs_pnl_fail; 1712 goto err_attached_crtsrc_file;
1635 1713
1636 ret = device_create_file(dev, &dev_attr_fbregs_crt); 1714 ret = device_create_file(dev, &dev_attr_fbregs_crt);
1637 if (ret) 1715 if (ret)
1638 goto fbregs_crt_fail; 1716 goto err_attached_pnlregs_file;
1639 1717
1640 /* we registered, return ok */ 1718 /* we registered, return ok */
1641 return 0; 1719 return 0;
1642 1720
1643 fbregs_crt_fail: 1721err_attached_pnlregs_file:
1644 device_remove_file(dev, &dev_attr_fbregs_pnl); 1722 device_remove_file(dev, &dev_attr_fbregs_pnl);
1645 1723
1646 fbregs_pnl_fail: 1724err_attached_crtsrc_file:
1647 device_remove_file(dev, &dev_attr_crt_src); 1725 device_remove_file(dev, &dev_attr_crt_src);
1648 1726
1649 crtsrc_fail: 1727err_started_panel:
1650 unregister_framebuffer(fbinfo_pnl); 1728 unregister_framebuffer(info->fb[HEAD_PANEL]);
1729 sm501_free_init_fb(info, HEAD_PANEL);
1651 1730
1652 register_pnl_fail: 1731err_started_crt:
1653 unregister_framebuffer(fbinfo_crt); 1732 unregister_framebuffer(info->fb[HEAD_CRT]);
1733 sm501_free_init_fb(info, HEAD_CRT);
1654 1734
1655 register_crt_fail: 1735err_started:
1656 sm501fb_stop(info); 1736 sm501fb_stop(info);
1657 1737
1658 sm501fb_start_fail: 1738err_probed_panel:
1659 sm501fb_info_release(info); 1739 framebuffer_release(info->fb[HEAD_PANEL]);
1660 1740
1661 sm501fb_alloc_fail: 1741err_probed_crt:
1662 framebuffer_release(fbinfo_pnl); 1742 framebuffer_release(info->fb[HEAD_CRT]);
1663 1743
1664 fbinfo_crt_alloc_fail: 1744err_alloc:
1665 framebuffer_release(fbinfo_crt); 1745 kfree(info);
1666 1746
1667 return ret; 1747 return ret;
1668} 1748}
@@ -1681,11 +1761,14 @@ static int sm501fb_remove(struct platform_device *pdev)
1681 device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); 1761 device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
1682 device_remove_file(&pdev->dev, &dev_attr_crt_src); 1762 device_remove_file(&pdev->dev, &dev_attr_crt_src);
1683 1763
1764 sm501_free_init_fb(info, HEAD_CRT);
1765 sm501_free_init_fb(info, HEAD_PANEL);
1766
1684 unregister_framebuffer(fbinfo_crt); 1767 unregister_framebuffer(fbinfo_crt);
1685 unregister_framebuffer(fbinfo_pnl); 1768 unregister_framebuffer(fbinfo_pnl);
1686 1769
1687 sm501fb_stop(info); 1770 sm501fb_stop(info);
1688 sm501fb_info_release(info); 1771 kfree(info);
1689 1772
1690 framebuffer_release(fbinfo_pnl); 1773 framebuffer_release(fbinfo_pnl);
1691 framebuffer_release(fbinfo_crt); 1774 framebuffer_release(fbinfo_crt);
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h
index 1a9a60c74be3..7fe5be4bc70e 100644
--- a/drivers/video/sticore.h
+++ b/drivers/video/sticore.h
@@ -352,8 +352,6 @@ struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
352 352
353/* functions to call the STI ROM directly */ 353/* functions to call the STI ROM directly */
354 354
355int sti_init_graph(struct sti_struct *sti);
356void sti_inq_conf(struct sti_struct *sti);
357void sti_putc(struct sti_struct *sti, int c, int y, int x); 355void sti_putc(struct sti_struct *sti, int c, int y, int x);
358void sti_set(struct sti_struct *sti, int src_y, int src_x, 356void sti_set(struct sti_struct *sti, int src_y, int src_x,
359 int height, int width, u8 color); 357 int height, int width, u8 color);
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 598d35eff935..166481402412 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1078,8 +1078,7 @@ static struct fb_ops stifb_ops = {
1078 * Initialization 1078 * Initialization
1079 */ 1079 */
1080 1080
1081int __init 1081static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
1082stifb_init_fb(struct sti_struct *sti, int bpp_pref)
1083{ 1082{
1084 struct fb_fix_screeninfo *fix; 1083 struct fb_fix_screeninfo *fix;
1085 struct fb_var_screeninfo *var; 1084 struct fb_var_screeninfo *var;
@@ -1315,8 +1314,7 @@ static int stifb_disabled __initdata;
1315int __init 1314int __init
1316stifb_setup(char *options); 1315stifb_setup(char *options);
1317 1316
1318int __init 1317static int __init stifb_init(void)
1319stifb_init(void)
1320{ 1318{
1321 struct sti_struct *sti; 1319 struct sti_struct *sti;
1322 struct sti_struct *def_sti; 1320 struct sti_struct *def_sti;
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 2a03f78bbb0d..643afbfe8277 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -505,7 +505,7 @@ static int __devexit tcx_remove(struct of_device *op)
505 return 0; 505 return 0;
506} 506}
507 507
508static struct of_device_id tcx_match[] = { 508static const struct of_device_id tcx_match[] = {
509 { 509 {
510 .name = "SUNW,tcx", 510 .name = "SUNW,tcx",
511 }, 511 },
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ea9f19d25597..14bd3f3680b8 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -95,7 +95,6 @@ static inline int mtrr_del(int reg, unsigned long base,
95#define VOODOO5_MAX_PIXCLOCK 350000 95#define VOODOO5_MAX_PIXCLOCK 350000
96 96
97static struct fb_fix_screeninfo tdfx_fix __devinitdata = { 97static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
98 .id = "3Dfx",
99 .type = FB_TYPE_PACKED_PIXELS, 98 .type = FB_TYPE_PACKED_PIXELS,
100 .visual = FB_VISUAL_PSEUDOCOLOR, 99 .visual = FB_VISUAL_PSEUDOCOLOR,
101 .ypanstep = 1, 100 .ypanstep = 1,
@@ -426,7 +425,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
426 if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) { 425 if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
427 /* Banshee/Voodoo3 */ 426 /* Banshee/Voodoo3 */
428 chip_size = 2; 427 chip_size = 2;
429 if (has_sgram && (draminit0 & DRAMINIT0_SGRAM_TYPE)) 428 if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE))
430 chip_size = 1; 429 chip_size = 1;
431 } else { 430 } else {
432 /* Voodoo4/5 */ 431 /* Voodoo4/5 */
@@ -836,16 +835,12 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
836 struct tdfx_par *par = info->par; 835 struct tdfx_par *par = info->par;
837 u32 addr = var->yoffset * info->fix.line_length; 836 u32 addr = var->yoffset * info->fix.line_length;
838 837
839 if (nopan || var->xoffset || (var->yoffset > var->yres_virtual)) 838 if (nopan || var->xoffset)
840 return -EINVAL;
841 if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
842 return -EINVAL; 839 return -EINVAL;
843 840
844 banshee_make_room(par, 1); 841 banshee_make_room(par, 1);
845 tdfx_outl(par, VIDDESKSTART, addr); 842 tdfx_outl(par, VIDDESKSTART, addr);
846 843
847 info->var.xoffset = var->xoffset;
848 info->var.yoffset = var->yoffset;
849 return 0; 844 return 0;
850} 845}
851 846
@@ -1200,57 +1195,58 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1200 return -ENOMEM; 1195 return -ENOMEM;
1201 1196
1202 default_par = info->par; 1197 default_par = info->par;
1198 info->fix = tdfx_fix;
1203 1199
1204 /* Configure the default fb_fix_screeninfo first */ 1200 /* Configure the default fb_fix_screeninfo first */
1205 switch (pdev->device) { 1201 switch (pdev->device) {
1206 case PCI_DEVICE_ID_3DFX_BANSHEE: 1202 case PCI_DEVICE_ID_3DFX_BANSHEE:
1207 strcat(tdfx_fix.id, " Banshee"); 1203 strcpy(info->fix.id, "3Dfx Banshee");
1208 default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK; 1204 default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
1209 break; 1205 break;
1210 case PCI_DEVICE_ID_3DFX_VOODOO3: 1206 case PCI_DEVICE_ID_3DFX_VOODOO3:
1211 strcat(tdfx_fix.id, " Voodoo3"); 1207 strcpy(info->fix.id, "3Dfx Voodoo3");
1212 default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK; 1208 default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
1213 break; 1209 break;
1214 case PCI_DEVICE_ID_3DFX_VOODOO5: 1210 case PCI_DEVICE_ID_3DFX_VOODOO5:
1215 strcat(tdfx_fix.id, " Voodoo5"); 1211 strcpy(info->fix.id, "3Dfx Voodoo5");
1216 default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK; 1212 default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
1217 break; 1213 break;
1218 } 1214 }
1219 1215
1220 tdfx_fix.mmio_start = pci_resource_start(pdev, 0); 1216 info->fix.mmio_start = pci_resource_start(pdev, 0);
1221 tdfx_fix.mmio_len = pci_resource_len(pdev, 0); 1217 info->fix.mmio_len = pci_resource_len(pdev, 0);
1222 if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len, 1218 if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
1223 "tdfx regbase")) { 1219 "tdfx regbase")) {
1224 printk(KERN_ERR "tdfxfb: Can't reserve regbase\n"); 1220 printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
1225 goto out_err; 1221 goto out_err;
1226 } 1222 }
1227 1223
1228 default_par->regbase_virt = 1224 default_par->regbase_virt =
1229 ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len); 1225 ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
1230 if (!default_par->regbase_virt) { 1226 if (!default_par->regbase_virt) {
1231 printk(KERN_ERR "fb: Can't remap %s register area.\n", 1227 printk(KERN_ERR "fb: Can't remap %s register area.\n",
1232 tdfx_fix.id); 1228 info->fix.id);
1233 goto out_err_regbase; 1229 goto out_err_regbase;
1234 } 1230 }
1235 1231
1236 tdfx_fix.smem_start = pci_resource_start(pdev, 1); 1232 info->fix.smem_start = pci_resource_start(pdev, 1);
1237 tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device); 1233 info->fix.smem_len = do_lfb_size(default_par, pdev->device);
1238 if (!tdfx_fix.smem_len) { 1234 if (!info->fix.smem_len) {
1239 printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id); 1235 printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
1240 goto out_err_regbase; 1236 goto out_err_regbase;
1241 } 1237 }
1242 1238
1243 if (!request_mem_region(tdfx_fix.smem_start, 1239 if (!request_mem_region(info->fix.smem_start,
1244 pci_resource_len(pdev, 1), "tdfx smem")) { 1240 pci_resource_len(pdev, 1), "tdfx smem")) {
1245 printk(KERN_ERR "tdfxfb: Can't reserve smem\n"); 1241 printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
1246 goto out_err_regbase; 1242 goto out_err_regbase;
1247 } 1243 }
1248 1244
1249 info->screen_base = ioremap_nocache(tdfx_fix.smem_start, 1245 info->screen_base = ioremap_nocache(info->fix.smem_start,
1250 tdfx_fix.smem_len); 1246 info->fix.smem_len);
1251 if (!info->screen_base) { 1247 if (!info->screen_base) {
1252 printk(KERN_ERR "fb: Can't remap %s framebuffer.\n", 1248 printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
1253 tdfx_fix.id); 1249 info->fix.id);
1254 goto out_err_screenbase; 1250 goto out_err_screenbase;
1255 } 1251 }
1256 1252
@@ -1262,20 +1258,19 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1262 goto out_err_screenbase; 1258 goto out_err_screenbase;
1263 } 1259 }
1264 1260
1265 printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id, 1261 printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
1266 tdfx_fix.smem_len >> 10); 1262 info->fix.smem_len >> 10);
1267 1263
1268 default_par->mtrr_handle = -1; 1264 default_par->mtrr_handle = -1;
1269 if (!nomtrr) 1265 if (!nomtrr)
1270 default_par->mtrr_handle = 1266 default_par->mtrr_handle =
1271 mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len, 1267 mtrr_add(info->fix.smem_start, info->fix.smem_len,
1272 MTRR_TYPE_WRCOMB, 1); 1268 MTRR_TYPE_WRCOMB, 1);
1273 1269
1274 tdfx_fix.ypanstep = nopan ? 0 : 1; 1270 info->fix.ypanstep = nopan ? 0 : 1;
1275 tdfx_fix.ywrapstep = nowrap ? 0 : 1; 1271 info->fix.ywrapstep = nowrap ? 0 : 1;
1276 1272
1277 info->fbops = &tdfxfb_ops; 1273 info->fbops = &tdfxfb_ops;
1278 info->fix = tdfx_fix;
1279 info->pseudo_palette = default_par->palette; 1274 info->pseudo_palette = default_par->palette;
1280 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1275 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1281#ifdef CONFIG_FB_3DFX_ACCEL 1276#ifdef CONFIG_FB_3DFX_ACCEL
@@ -1328,14 +1323,14 @@ out_err_iobase:
1328out_err_screenbase: 1323out_err_screenbase:
1329 if (info->screen_base) 1324 if (info->screen_base)
1330 iounmap(info->screen_base); 1325 iounmap(info->screen_base);
1331 release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1)); 1326 release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
1332out_err_regbase: 1327out_err_regbase:
1333 /* 1328 /*
1334 * Cleanup after anything that was remapped/allocated. 1329 * Cleanup after anything that was remapped/allocated.
1335 */ 1330 */
1336 if (default_par->regbase_virt) 1331 if (default_par->regbase_virt)
1337 iounmap(default_par->regbase_virt); 1332 iounmap(default_par->regbase_virt);
1338 release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len); 1333 release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1339out_err: 1334out_err:
1340 framebuffer_release(info); 1335 framebuffer_release(info);
1341 return -ENXIO; 1336 return -ENXIO;
@@ -1426,6 +1421,8 @@ MODULE_LICENSE("GPL");
1426module_param(hwcursor, int, 0644); 1421module_param(hwcursor, int, 0644);
1427MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " 1422MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
1428 "(1=enable, 0=disable, default=1)"); 1423 "(1=enable, 0=disable, default=1)");
1424module_param(mode_option, charp, 0);
1425MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
1429#ifdef CONFIG_MTRR 1426#ifdef CONFIG_MTRR
1430module_param(nomtrr, bool, 0); 1427module_param(nomtrr, bool, 0);
1431MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)"); 1428MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
new file mode 100644
index 000000000000..2a380011e9ba
--- /dev/null
+++ b/drivers/video/tmiofb.c
@@ -0,0 +1,1050 @@
1/*
2 * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
3 *
4 * Copyright(C) 2005-2006 Chris Humbert
5 * Copyright(C) 2005 Dirk Opfer
6 * Copytight(C) 2007,2008 Dmitry Baryshkov
7 *
8 * Based on:
9 * drivers/video/w100fb.c
10 * code written by Sharp/Lineo for 2.4 kernels
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2
14 * as published by the Free Software Foundation;
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/fb.h>
26#include <linux/interrupt.h>
27#include <linux/delay.h>
28/* Why should fb driver call console functions? because acquire_console_sem() */
29#include <linux/console.h>
30#include <linux/mfd/core.h>
31#include <linux/mfd/tmio.h>
32#include <linux/uaccess.h>
33
34/*
35 * accelerator commands
36 */
37#define TMIOFB_ACC_CSADR(x) (0x00000000 | ((x) & 0x001ffffe))
38#define TMIOFB_ACC_CHPIX(x) (0x01000000 | ((x) & 0x000003ff))
39#define TMIOFB_ACC_CVPIX(x) (0x02000000 | ((x) & 0x000003ff))
40#define TMIOFB_ACC_PSADR(x) (0x03000000 | ((x) & 0x00fffffe))
41#define TMIOFB_ACC_PHPIX(x) (0x04000000 | ((x) & 0x000003ff))
42#define TMIOFB_ACC_PVPIX(x) (0x05000000 | ((x) & 0x000003ff))
43#define TMIOFB_ACC_PHOFS(x) (0x06000000 | ((x) & 0x000003ff))
44#define TMIOFB_ACC_PVOFS(x) (0x07000000 | ((x) & 0x000003ff))
45#define TMIOFB_ACC_POADR(x) (0x08000000 | ((x) & 0x00fffffe))
46#define TMIOFB_ACC_RSTR(x) (0x09000000 | ((x) & 0x000000ff))
47#define TMIOFB_ACC_TCLOR(x) (0x0A000000 | ((x) & 0x0000ffff))
48#define TMIOFB_ACC_FILL(x) (0x0B000000 | ((x) & 0x0000ffff))
49#define TMIOFB_ACC_DSADR(x) (0x0C000000 | ((x) & 0x00fffffe))
50#define TMIOFB_ACC_SSADR(x) (0x0D000000 | ((x) & 0x00fffffe))
51#define TMIOFB_ACC_DHPIX(x) (0x0E000000 | ((x) & 0x000003ff))
52#define TMIOFB_ACC_DVPIX(x) (0x0F000000 | ((x) & 0x000003ff))
53#define TMIOFB_ACC_SHPIX(x) (0x10000000 | ((x) & 0x000003ff))
54#define TMIOFB_ACC_SVPIX(x) (0x11000000 | ((x) & 0x000003ff))
55#define TMIOFB_ACC_LBINI(x) (0x12000000 | ((x) & 0x0000ffff))
56#define TMIOFB_ACC_LBK2(x) (0x13000000 | ((x) & 0x0000ffff))
57#define TMIOFB_ACC_SHBINI(x) (0x14000000 | ((x) & 0x0000ffff))
58#define TMIOFB_ACC_SHBK2(x) (0x15000000 | ((x) & 0x0000ffff))
59#define TMIOFB_ACC_SVBINI(x) (0x16000000 | ((x) & 0x0000ffff))
60#define TMIOFB_ACC_SVBK2(x) (0x17000000 | ((x) & 0x0000ffff))
61
62#define TMIOFB_ACC_CMGO 0x20000000
63#define TMIOFB_ACC_CMGO_CEND 0x00000001
64#define TMIOFB_ACC_CMGO_INT 0x00000002
65#define TMIOFB_ACC_CMGO_CMOD 0x00000010
66#define TMIOFB_ACC_CMGO_CDVRV 0x00000020
67#define TMIOFB_ACC_CMGO_CDHRV 0x00000040
68#define TMIOFB_ACC_CMGO_RUND 0x00008000
69#define TMIOFB_ACC_SCGO 0x21000000
70#define TMIOFB_ACC_SCGO_CEND 0x00000001
71#define TMIOFB_ACC_SCGO_INT 0x00000002
72#define TMIOFB_ACC_SCGO_ROP3 0x00000004
73#define TMIOFB_ACC_SCGO_TRNS 0x00000008
74#define TMIOFB_ACC_SCGO_DVRV 0x00000010
75#define TMIOFB_ACC_SCGO_DHRV 0x00000020
76#define TMIOFB_ACC_SCGO_SVRV 0x00000040
77#define TMIOFB_ACC_SCGO_SHRV 0x00000080
78#define TMIOFB_ACC_SCGO_DSTXY 0x00008000
79#define TMIOFB_ACC_SBGO 0x22000000
80#define TMIOFB_ACC_SBGO_CEND 0x00000001
81#define TMIOFB_ACC_SBGO_INT 0x00000002
82#define TMIOFB_ACC_SBGO_DVRV 0x00000010
83#define TMIOFB_ACC_SBGO_DHRV 0x00000020
84#define TMIOFB_ACC_SBGO_SVRV 0x00000040
85#define TMIOFB_ACC_SBGO_SHRV 0x00000080
86#define TMIOFB_ACC_SBGO_SBMD 0x00000100
87#define TMIOFB_ACC_FLGO 0x23000000
88#define TMIOFB_ACC_FLGO_CEND 0x00000001
89#define TMIOFB_ACC_FLGO_INT 0x00000002
90#define TMIOFB_ACC_FLGO_ROP3 0x00000004
91#define TMIOFB_ACC_LDGO 0x24000000
92#define TMIOFB_ACC_LDGO_CEND 0x00000001
93#define TMIOFB_ACC_LDGO_INT 0x00000002
94#define TMIOFB_ACC_LDGO_ROP3 0x00000004
95#define TMIOFB_ACC_LDGO_ENDPX 0x00000008
96#define TMIOFB_ACC_LDGO_LVRV 0x00000010
97#define TMIOFB_ACC_LDGO_LHRV 0x00000020
98#define TMIOFB_ACC_LDGO_LDMOD 0x00000040
99
100/* a FIFO is always allocated, even if acceleration is not used */
101#define TMIOFB_FIFO_SIZE 512
102
103/*
104 * LCD Host Controller Configuration Register
105 *
106 * This iomem area supports only 16-bit IO.
107 */
108#define CCR_CMD 0x04 /* Command */
109#define CCR_REVID 0x08 /* Revision ID */
110#define CCR_BASEL 0x10 /* LCD Control Reg Base Addr Low */
111#define CCR_BASEH 0x12 /* LCD Control Reg Base Addr High */
112#define CCR_UGCC 0x40 /* Unified Gated Clock Control */
113#define CCR_GCC 0x42 /* Gated Clock Control */
114#define CCR_USC 0x50 /* Unified Software Clear */
115#define CCR_VRAMRTC 0x60 /* VRAM Timing Control */
116 /* 0x61 VRAM Refresh Control */
117#define CCR_VRAMSAC 0x62 /* VRAM Access Control */
118 /* 0x63 VRAM Status */
119#define CCR_VRAMBC 0x64 /* VRAM Block Control */
120
121/*
122 * LCD Control Register
123 *
124 * This iomem area supports only 16-bit IO.
125 */
126#define LCR_UIS 0x000 /* Unified Interrupt Status */
127#define LCR_VHPN 0x008 /* VRAM Horizontal Pixel Number */
128#define LCR_CFSAL 0x00a /* Command FIFO Start Address Low */
129#define LCR_CFSAH 0x00c /* Command FIFO Start Address High */
130#define LCR_CFS 0x00e /* Command FIFO Size */
131#define LCR_CFWS 0x010 /* Command FIFO Writeable Size */
132#define LCR_BBIE 0x012 /* BitBLT Interrupt Enable */
133#define LCR_BBISC 0x014 /* BitBLT Interrupt Status and Clear */
134#define LCR_CCS 0x016 /* Command Count Status */
135#define LCR_BBES 0x018 /* BitBLT Execution Status */
136#define LCR_CMDL 0x01c /* Command Low */
137#define LCR_CMDH 0x01e /* Command High */
138#define LCR_CFC 0x022 /* Command FIFO Clear */
139#define LCR_CCIFC 0x024 /* CMOS Camera IF Control */
140#define LCR_HWT 0x026 /* Hardware Test */
141#define LCR_LCDCCRC 0x100 /* LCDC Clock and Reset Control */
142#define LCR_LCDCC 0x102 /* LCDC Control */
143#define LCR_LCDCOPC 0x104 /* LCDC Output Pin Control */
144#define LCR_LCDIS 0x108 /* LCD Interrupt Status */
145#define LCR_LCDIM 0x10a /* LCD Interrupt Mask */
146#define LCR_LCDIE 0x10c /* LCD Interrupt Enable */
147#define LCR_GDSAL 0x122 /* Graphics Display Start Address Low */
148#define LCR_GDSAH 0x124 /* Graphics Display Start Address High */
149#define LCR_VHPCL 0x12a /* VRAM Horizontal Pixel Count Low */
150#define LCR_VHPCH 0x12c /* VRAM Horizontal Pixel Count High */
151#define LCR_GM 0x12e /* Graphic Mode(VRAM access enable) */
152#define LCR_HT 0x140 /* Horizontal Total */
153#define LCR_HDS 0x142 /* Horizontal Display Start */
154#define LCR_HSS 0x144 /* H-Sync Start */
155#define LCR_HSE 0x146 /* H-Sync End */
156#define LCR_HNP 0x14c /* Horizontal Number of Pixels */
157#define LCR_VT 0x150 /* Vertical Total */
158#define LCR_VDS 0x152 /* Vertical Display Start */
159#define LCR_VSS 0x154 /* V-Sync Start */
160#define LCR_VSE 0x156 /* V-Sync End */
161#define LCR_CDLN 0x160 /* Current Display Line Number */
162#define LCR_ILN 0x162 /* Interrupt Line Number */
163#define LCR_SP 0x164 /* Sync Polarity */
164#define LCR_MISC 0x166 /* MISC(RGB565 mode) */
165#define LCR_VIHSS 0x16a /* Video Interface H-Sync Start */
166#define LCR_VIVS 0x16c /* Video Interface Vertical Start */
167#define LCR_VIVE 0x16e /* Video Interface Vertical End */
168#define LCR_VIVSS 0x170 /* Video Interface V-Sync Start */
169#define LCR_VCCIS 0x17e /* Video / CMOS Camera Interface Select */
170#define LCR_VIDWSAL 0x180 /* VI Data Write Start Address Low */
171#define LCR_VIDWSAH 0x182 /* VI Data Write Start Address High */
172#define LCR_VIDRSAL 0x184 /* VI Data Read Start Address Low */
173#define LCR_VIDRSAH 0x186 /* VI Data Read Start Address High */
174#define LCR_VIPDDST 0x188 /* VI Picture Data Display Start Timing */
175#define LCR_VIPDDET 0x186 /* VI Picture Data Display End Timing */
176#define LCR_VIE 0x18c /* Video Interface Enable */
177#define LCR_VCS 0x18e /* Video/Camera Select */
178#define LCR_VPHWC 0x194 /* Video Picture Horizontal Wait Count */
179#define LCR_VPHS 0x196 /* Video Picture Horizontal Size */
180#define LCR_VPVWC 0x198 /* Video Picture Vertical Wait Count */
181#define LCR_VPVS 0x19a /* Video Picture Vertical Size */
182#define LCR_PLHPIX 0x1a0 /* PLHPIX */
183#define LCR_XS 0x1a2 /* XStart */
184#define LCR_XCKHW 0x1a4 /* XCK High Width */
185#define LCR_STHS 0x1a8 /* STH Start */
186#define LCR_VT2 0x1aa /* Vertical Total */
187#define LCR_YCKSW 0x1ac /* YCK Start Wait */
188#define LCR_YSTS 0x1ae /* YST Start */
189#define LCR_PPOLS 0x1b0 /* #PPOL Start */
190#define LCR_PRECW 0x1b2 /* PREC Width */
191#define LCR_VCLKHW 0x1b4 /* VCLK High Width */
192#define LCR_OC 0x1b6 /* Output Control */
193
194static char *mode_option __devinitdata;
195
196struct tmiofb_par {
197 u32 pseudo_palette[16];
198
199#ifdef CONFIG_FB_TMIO_ACCELL
200 wait_queue_head_t wait_acc;
201 bool use_polling;
202#endif
203
204 void __iomem *ccr;
205 void __iomem *lcr;
206};
207
208/*--------------------------------------------------------------------------*/
209
210/*
211 * reasons for an interrupt:
212 * uis bbisc lcdis
213 * 0100 0001 accelerator command completed
214 * 2000 0001 vsync start
215 * 2000 0002 display start
216 * 2000 0004 line number match(0x1ff mask???)
217 */
218static irqreturn_t tmiofb_irq(int irq, void *__info)
219{
220 struct fb_info *info = __info;
221 struct tmiofb_par *par = info->par;
222 unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
223
224
225 /*
226 * We were in polling mode and now we got correct irq.
227 * Switch back to IRQ-based sync of command FIFO
228 */
229 if (unlikely(par->use_polling && irq != -1)) {
230 printk(KERN_INFO "tmiofb: switching to waitq\n");
231 par->use_polling = false;
232 }
233
234 tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
235
236#ifdef CONFIG_FB_TMIO_ACCELL
237 if (bbisc & 1)
238 wake_up(&par->wait_acc);
239#endif
240
241 return IRQ_HANDLED;
242}
243
244
245/*--------------------------------------------------------------------------*/
246
247
248/*
249 * Turns off the LCD controller and LCD host controller.
250 */
251static int tmiofb_hw_stop(struct platform_device *dev)
252{
253 struct mfd_cell *cell = dev->dev.platform_data;
254 struct tmio_fb_data *data = cell->driver_data;
255 struct fb_info *info = platform_get_drvdata(dev);
256 struct tmiofb_par *par = info->par;
257
258 tmio_iowrite16(0, par->ccr + CCR_UGCC);
259 tmio_iowrite16(0, par->lcr + LCR_GM);
260 data->lcd_set_power(dev, 0);
261 tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
262
263 return 0;
264}
265
266/*
267 * Initializes the LCD host controller.
268 */
269static int tmiofb_hw_init(struct platform_device *dev)
270{
271 struct mfd_cell *cell = dev->dev.platform_data;
272 struct fb_info *info = platform_get_drvdata(dev);
273 struct tmiofb_par *par = info->par;
274 const struct resource *nlcr = &cell->resources[0];
275 const struct resource *vram = &cell->resources[2];
276 unsigned long base;
277
278 if (nlcr == NULL || vram == NULL)
279 return -EINVAL;
280
281 base = nlcr->start;
282
283 tmio_iowrite16(0x003a, par->ccr + CCR_UGCC);
284 tmio_iowrite16(0x003a, par->ccr + CCR_GCC);
285 tmio_iowrite16(0x3f00, par->ccr + CCR_USC);
286
287 msleep(2); /* wait for device to settle */
288
289 tmio_iowrite16(0x0000, par->ccr + CCR_USC);
290 tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH);
291 tmio_iowrite16(base, par->ccr + CCR_BASEL);
292 tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */
293 tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */
294 tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */
295 tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC);
296 msleep(2); /* wait for device to settle */
297 tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC);
298
299 base = vram->start + info->screen_size;
300 tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH);
301 tmio_iowrite16(base, par->lcr + LCR_CFSAL);
302 tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS);
303 tmio_iowrite16(1, par->lcr + LCR_CFC);
304 tmio_iowrite16(1, par->lcr + LCR_BBIE);
305 tmio_iowrite16(0, par->lcr + LCR_CFWS);
306
307 return 0;
308}
309
310/*
311 * Sets the LCD controller's output resolution and pixel clock
312 */
313static void tmiofb_hw_mode(struct platform_device *dev)
314{
315 struct mfd_cell *cell = dev->dev.platform_data;
316 struct tmio_fb_data *data = cell->driver_data;
317 struct fb_info *info = platform_get_drvdata(dev);
318 struct fb_videomode *mode = info->mode;
319 struct tmiofb_par *par = info->par;
320 unsigned int i;
321
322 tmio_iowrite16(0, par->lcr + LCR_GM);
323 data->lcd_set_power(dev, 0);
324 tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
325 data->lcd_mode(dev, mode);
326 data->lcd_set_power(dev, 1);
327
328 tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN);
329 tmio_iowrite16(0, par->lcr + LCR_GDSAH);
330 tmio_iowrite16(0, par->lcr + LCR_GDSAL);
331 tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH);
332 tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL);
333 tmio_iowrite16(i = 0, par->lcr + LCR_HSS);
334 tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE);
335 tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS);
336 tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT);
337 tmio_iowrite16(mode->xres, par->lcr + LCR_HNP);
338 tmio_iowrite16(i = 0, par->lcr + LCR_VSS);
339 tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE);
340 tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS);
341 tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN);
342 tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT);
343 tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */
344 tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */
345 tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC);
346 tmio_iowrite16(3, par->lcr + LCR_SP); /* sync polarity */
347
348 tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
349 msleep(5); /* wait for device to settle */
350 tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */
351 msleep(5); /* wait for device to settle */
352 tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/
353 tmio_iowrite16(0xfffa, par->lcr + LCR_VCS);
354}
355
356/*--------------------------------------------------------------------------*/
357
358#ifdef CONFIG_FB_TMIO_ACCELL
359static int __must_check
360tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
361{
362 struct tmiofb_par *par = info->par;
363 /*
364 * This code can be called whith interrupts disabled.
365 * So instead of relaying on irq to trigger the event,
366 * poll the state till the necessary command is executed.
367 */
368 if (irqs_disabled() || par->use_polling) {
369 int i = 0;
370 while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) {
371 udelay(1);
372 i++;
373 if (i > 10000) {
374 pr_err("tmiofb: timeout waiting for %d\n",
375 ccs);
376 return -ETIMEDOUT;
377 }
378 tmiofb_irq(-1, info);
379 }
380 } else {
381 if (!wait_event_interruptible_timeout(par->wait_acc,
382 tmio_ioread16(par->lcr + LCR_CCS) <= ccs,
383 1000)) {
384 pr_err("tmiofb: timeout waiting for %d\n", ccs);
385 return -ETIMEDOUT;
386 }
387 }
388
389 return 0;
390}
391
392/*
393 * Writes an accelerator command to the accelerator's FIFO.
394 */
395static int
396tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
397{
398 struct tmiofb_par *par = info->par;
399 int ret;
400
401 ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
402 if (ret)
403 return ret;
404
405 for (; count; count--, cmd++) {
406 tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH);
407 tmio_iowrite16(*cmd, par->lcr + LCR_CMDL);
408 }
409
410 return ret;
411}
412
413/*
414 * Wait for the accelerator to finish its operations before writing
415 * to the framebuffer for consistent display output.
416 */
417static int tmiofb_sync(struct fb_info *fbi)
418{
419 struct tmiofb_par *par = fbi->par;
420
421 int ret;
422 int i = 0;
423
424 ret = tmiofb_acc_wait(fbi, 0);
425
426 while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */
427 udelay(1);
428 i++ ;
429 if (i > 10000) {
430 printk(KERN_ERR "timeout waiting for blit to end!\n");
431 return -ETIMEDOUT;
432 }
433 }
434
435 return ret;
436}
437
438static void
439tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
440{
441 const u32 cmd[] = {
442 TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
443 TMIOFB_ACC_DHPIX(rect->width - 1),
444 TMIOFB_ACC_DVPIX(rect->height - 1),
445 TMIOFB_ACC_FILL(rect->color),
446 TMIOFB_ACC_FLGO,
447 };
448
449 if (fbi->state != FBINFO_STATE_RUNNING ||
450 fbi->flags & FBINFO_HWACCEL_DISABLED) {
451 cfb_fillrect(fbi, rect);
452 return;
453 }
454
455 tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
456}
457
458static void
459tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
460{
461 const u32 cmd[] = {
462 TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
463 TMIOFB_ACC_DHPIX(area->width - 1),
464 TMIOFB_ACC_DVPIX(area->height - 1),
465 TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
466 TMIOFB_ACC_SCGO,
467 };
468
469 if (fbi->state != FBINFO_STATE_RUNNING ||
470 fbi->flags & FBINFO_HWACCEL_DISABLED) {
471 cfb_copyarea(fbi, area);
472 return;
473 }
474
475 tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
476}
477#endif
478
479static void tmiofb_clearscreen(struct fb_info *info)
480{
481 const struct fb_fillrect rect = {
482 .dx = 0,
483 .dy = 0,
484 .width = info->mode->xres,
485 .height = info->mode->yres,
486 .color = 0,
487 .rop = ROP_COPY,
488 };
489
490 info->fbops->fb_fillrect(info, &rect);
491}
492
493static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
494{
495 struct tmiofb_par *par = fbi->par;
496 struct fb_videomode *mode = fbi->mode;
497 unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN);
498 unsigned int vds = mode->vsync_len + mode->upper_margin;
499
500 vblank->vcount = vcount;
501 vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
502 | FB_VBLANK_HAVE_VSYNC;
503
504 if (vcount < mode->vsync_len)
505 vblank->flags |= FB_VBLANK_VSYNCING;
506
507 if (vcount < vds || vcount > vds + mode->yres)
508 vblank->flags |= FB_VBLANK_VBLANKING;
509
510 return 0;
511}
512
513
514static int tmiofb_ioctl(struct fb_info *fbi,
515 unsigned int cmd, unsigned long arg)
516{
517 switch (cmd) {
518 case FBIOGET_VBLANK: {
519 struct fb_vblank vblank = {0};
520 void __user *argp = (void __user *) arg;
521
522 tmiofb_vblank(fbi, &vblank);
523 if (copy_to_user(argp, &vblank, sizeof vblank))
524 return -EFAULT;
525 return 0;
526 }
527
528#ifdef CONFIG_FB_TMIO_ACCELL
529 case FBIO_TMIO_ACC_SYNC:
530 tmiofb_sync(fbi);
531 return 0;
532
533 case FBIO_TMIO_ACC_WRITE: {
534 u32 __user *argp = (void __user *) arg;
535 u32 len;
536 u32 acc[16];
537
538 if (get_user(len, argp))
539 return -EFAULT;
540 if (len > ARRAY_SIZE(acc))
541 return -EINVAL;
542 if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
543 return -EFAULT;
544
545 return tmiofb_acc_write(fbi, acc, len);
546 }
547#endif
548 }
549
550 return -ENOTTY;
551}
552
553/*--------------------------------------------------------------------------*/
554
555/* Select the smallest mode that allows the desired resolution to be
556 * displayed. If desired, the x and y parameters can be rounded up to
557 * match the selected mode.
558 */
559static struct fb_videomode *
560tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
561{
562 struct mfd_cell *cell =
563 info->device->platform_data;
564 struct tmio_fb_data *data = cell->driver_data;
565 struct fb_videomode *best = NULL;
566 int i;
567
568 for (i = 0; i < data->num_modes; i++) {
569 struct fb_videomode *mode = data->modes + i;
570
571 if (mode->xres >= var->xres && mode->yres >= var->yres
572 && (!best || (mode->xres < best->xres
573 && mode->yres < best->yres)))
574 best = mode;
575 }
576
577 return best;
578}
579
580static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
581{
582
583 struct fb_videomode *mode;
584 struct mfd_cell *cell =
585 info->device->platform_data;
586 struct tmio_fb_data *data = cell->driver_data;
587
588 mode = tmiofb_find_mode(info, var);
589 if (!mode || var->bits_per_pixel > 16)
590 return -EINVAL;
591
592 fb_videomode_to_var(var, mode);
593
594 var->xres_virtual = mode->xres;
595 var->yres_virtual = info->screen_size / (mode->xres * 2);
596
597 if (var->yres_virtual < var->yres)
598 return -EINVAL;
599
600 var->xoffset = 0;
601 var->yoffset = 0;
602 var->bits_per_pixel = 16;
603 var->grayscale = 0;
604 var->red.offset = 11;
605 var->red.length = 5;
606 var->green.offset = 5;
607 var->green.length = 6;
608 var->blue.offset = 0;
609 var->blue.length = 5;
610 var->transp.offset = 0;
611 var->transp.length = 0;
612 var->nonstd = 0;
613 var->height = data->height; /* mm */
614 var->width = data->width; /* mm */
615 var->rotate = 0;
616 return 0;
617}
618
619static int tmiofb_set_par(struct fb_info *info)
620{
621 struct fb_var_screeninfo *var = &info->var;
622 struct fb_videomode *mode;
623
624 mode = tmiofb_find_mode(info, var);
625 if (!mode)
626 return -EINVAL;
627
628 info->mode = mode;
629 info->fix.line_length = info->mode->xres *
630 var->bits_per_pixel / 8;
631
632 tmiofb_hw_mode(to_platform_device(info->device));
633 tmiofb_clearscreen(info);
634 return 0;
635}
636
637static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
638 unsigned blue, unsigned transp,
639 struct fb_info *info)
640{
641 struct tmiofb_par *par = info->par;
642
643 if (regno < ARRAY_SIZE(par->pseudo_palette)) {
644 par->pseudo_palette[regno] =
645 ((red & 0xf800)) |
646 ((green & 0xfc00) >> 5) |
647 ((blue & 0xf800) >> 11);
648 return 0;
649 }
650
651 return -EINVAL;
652}
653
654static int tmiofb_blank(int blank, struct fb_info *info)
655{
656 /*
657 * everything is done in lcd/bl drivers.
658 * this is purely to make sysfs happy and work.
659 */
660 return 0;
661}
662
663static struct fb_ops tmiofb_ops = {
664 .owner = THIS_MODULE,
665
666 .fb_ioctl = tmiofb_ioctl,
667 .fb_check_var = tmiofb_check_var,
668 .fb_set_par = tmiofb_set_par,
669 .fb_setcolreg = tmiofb_setcolreg,
670 .fb_blank = tmiofb_blank,
671 .fb_imageblit = cfb_imageblit,
672#ifdef CONFIG_FB_TMIO_ACCELL
673 .fb_sync = tmiofb_sync,
674 .fb_fillrect = tmiofb_fillrect,
675 .fb_copyarea = tmiofb_copyarea,
676#else
677 .fb_fillrect = cfb_fillrect,
678 .fb_copyarea = cfb_copyarea,
679#endif
680};
681
682/*--------------------------------------------------------------------------*/
683
684static int __devinit tmiofb_probe(struct platform_device *dev)
685{
686 struct mfd_cell *cell = dev->dev.platform_data;
687 struct tmio_fb_data *data = cell->driver_data;
688 struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
689 struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
690 struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
691 int irq = platform_get_irq(dev, 0);
692 struct fb_info *info;
693 struct tmiofb_par *par;
694 int retval;
695
696 /*
697 * This is the only way ATM to disable the fb
698 */
699 if (data == NULL) {
700 dev_err(&dev->dev, "NULL platform data!\n");
701 return -EINVAL;
702 }
703
704 info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
705
706 if (!info)
707 return -ENOMEM;
708
709 par = info->par;
710
711#ifdef CONFIG_FB_TMIO_ACCELL
712 init_waitqueue_head(&par->wait_acc);
713
714 par->use_polling = true;
715
716 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
717 | FBINFO_HWACCEL_FILLRECT;
718#else
719 info->flags = FBINFO_DEFAULT;
720#endif
721
722 info->fbops = &tmiofb_ops;
723
724 strcpy(info->fix.id, "tmio-fb");
725 info->fix.smem_start = vram->start;
726 info->fix.smem_len = resource_size(vram);
727 info->fix.type = FB_TYPE_PACKED_PIXELS;
728 info->fix.visual = FB_VISUAL_TRUECOLOR;
729 info->fix.mmio_start = lcr->start;
730 info->fix.mmio_len = resource_size(lcr);
731 info->fix.accel = FB_ACCEL_NONE;
732 info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
733 info->pseudo_palette = par->pseudo_palette;
734
735 par->ccr = ioremap(ccr->start, resource_size(ccr));
736 if (!par->ccr) {
737 retval = -ENOMEM;
738 goto err_ioremap_ccr;
739 }
740
741 par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
742 if (!par->lcr) {
743 retval = -ENOMEM;
744 goto err_ioremap_lcr;
745 }
746
747 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
748 if (!info->screen_base) {
749 retval = -ENOMEM;
750 goto err_ioremap_vram;
751 }
752
753 retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED,
754 dev->dev.bus_id, info);
755
756 if (retval)
757 goto err_request_irq;
758
759 platform_set_drvdata(dev, info);
760
761 retval = fb_find_mode(&info->var, info, mode_option,
762 data->modes, data->num_modes,
763 data->modes, 16);
764 if (!retval) {
765 retval = -EINVAL;
766 goto err_find_mode;
767 }
768
769 if (cell->enable) {
770 retval = cell->enable(dev);
771 if (retval)
772 goto err_enable;
773 }
774
775 retval = tmiofb_hw_init(dev);
776 if (retval)
777 goto err_hw_init;
778
779 fb_videomode_to_modelist(data->modes, data->num_modes,
780 &info->modelist);
781
782 retval = register_framebuffer(info);
783 if (retval < 0)
784 goto err_register_framebuffer;
785
786 printk(KERN_INFO "fb%d: %s frame buffer device\n",
787 info->node, info->fix.id);
788
789 return 0;
790
791err_register_framebuffer:
792/*err_set_par:*/
793 tmiofb_hw_stop(dev);
794err_hw_init:
795 if (cell->disable)
796 cell->disable(dev);
797err_enable:
798err_find_mode:
799 platform_set_drvdata(dev, NULL);
800 free_irq(irq, info);
801err_request_irq:
802 iounmap(info->screen_base);
803err_ioremap_vram:
804 iounmap(par->lcr);
805err_ioremap_lcr:
806 iounmap(par->ccr);
807err_ioremap_ccr:
808 framebuffer_release(info);
809 return retval;
810}
811
812static int __devexit tmiofb_remove(struct platform_device *dev)
813{
814 struct mfd_cell *cell = dev->dev.platform_data;
815 struct fb_info *info = platform_get_drvdata(dev);
816 int irq = platform_get_irq(dev, 0);
817 struct tmiofb_par *par;
818
819 if (info) {
820 par = info->par;
821 unregister_framebuffer(info);
822
823 tmiofb_hw_stop(dev);
824
825 if (cell->disable)
826 cell->disable(dev);
827
828 platform_set_drvdata(dev, NULL);
829
830 free_irq(irq, info);
831
832 iounmap(info->screen_base);
833 iounmap(par->lcr);
834 iounmap(par->ccr);
835
836 framebuffer_release(info);
837 }
838
839 return 0;
840}
841
842#ifdef DEBUG
843static void tmiofb_dump_regs(struct platform_device *dev)
844{
845 struct fb_info *info = platform_get_drvdata(dev);
846 struct tmiofb_par *par = info->par;
847
848 printk(KERN_DEBUG "lhccr:\n");
849#define CCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
850 tmio_ioread16(par->ccr + CCR_ ## n));
851 CCR_PR(CMD);
852 CCR_PR(REVID);
853 CCR_PR(BASEL);
854 CCR_PR(BASEH);
855 CCR_PR(UGCC);
856 CCR_PR(GCC);
857 CCR_PR(USC);
858 CCR_PR(VRAMRTC);
859 CCR_PR(VRAMSAC);
860 CCR_PR(VRAMBC);
861#undef CCR_PR
862
863 printk(KERN_DEBUG "lcr: \n");
864#define LCR_PR(n) printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
865 tmio_ioread16(par->lcr + LCR_ ## n));
866 LCR_PR(UIS);
867 LCR_PR(VHPN);
868 LCR_PR(CFSAL);
869 LCR_PR(CFSAH);
870 LCR_PR(CFS);
871 LCR_PR(CFWS);
872 LCR_PR(BBIE);
873 LCR_PR(BBISC);
874 LCR_PR(CCS);
875 LCR_PR(BBES);
876 LCR_PR(CMDL);
877 LCR_PR(CMDH);
878 LCR_PR(CFC);
879 LCR_PR(CCIFC);
880 LCR_PR(HWT);
881 LCR_PR(LCDCCRC);
882 LCR_PR(LCDCC);
883 LCR_PR(LCDCOPC);
884 LCR_PR(LCDIS);
885 LCR_PR(LCDIM);
886 LCR_PR(LCDIE);
887 LCR_PR(GDSAL);
888 LCR_PR(GDSAH);
889 LCR_PR(VHPCL);
890 LCR_PR(VHPCH);
891 LCR_PR(GM);
892 LCR_PR(HT);
893 LCR_PR(HDS);
894 LCR_PR(HSS);
895 LCR_PR(HSE);
896 LCR_PR(HNP);
897 LCR_PR(VT);
898 LCR_PR(VDS);
899 LCR_PR(VSS);
900 LCR_PR(VSE);
901 LCR_PR(CDLN);
902 LCR_PR(ILN);
903 LCR_PR(SP);
904 LCR_PR(MISC);
905 LCR_PR(VIHSS);
906 LCR_PR(VIVS);
907 LCR_PR(VIVE);
908 LCR_PR(VIVSS);
909 LCR_PR(VCCIS);
910 LCR_PR(VIDWSAL);
911 LCR_PR(VIDWSAH);
912 LCR_PR(VIDRSAL);
913 LCR_PR(VIDRSAH);
914 LCR_PR(VIPDDST);
915 LCR_PR(VIPDDET);
916 LCR_PR(VIE);
917 LCR_PR(VCS);
918 LCR_PR(VPHWC);
919 LCR_PR(VPHS);
920 LCR_PR(VPVWC);
921 LCR_PR(VPVS);
922 LCR_PR(PLHPIX);
923 LCR_PR(XS);
924 LCR_PR(XCKHW);
925 LCR_PR(STHS);
926 LCR_PR(VT2);
927 LCR_PR(YCKSW);
928 LCR_PR(YSTS);
929 LCR_PR(PPOLS);
930 LCR_PR(PRECW);
931 LCR_PR(VCLKHW);
932 LCR_PR(OC);
933#undef LCR_PR
934}
935#endif
936
937#ifdef CONFIG_PM
938static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
939{
940 struct fb_info *info = platform_get_drvdata(dev);
941 struct tmiofb_par *par = info->par;
942 struct mfd_cell *cell = dev->dev.platform_data;
943 int retval = 0;
944
945 acquire_console_sem();
946
947 fb_set_suspend(info, 1);
948
949 if (info->fbops->fb_sync)
950 info->fbops->fb_sync(info);
951
952
953 /*
954 * The fb should be usable even if interrupts are disabled (and they are
955 * during suspend/resume). Switch temporary to forced polling.
956 */
957 printk(KERN_INFO "tmiofb: switching to polling\n");
958 par->use_polling = true;
959 tmiofb_hw_stop(dev);
960
961 if (cell->suspend)
962 retval = cell->suspend(dev);
963
964 release_console_sem();
965
966 return retval;
967}
968
969static int tmiofb_resume(struct platform_device *dev)
970{
971 struct fb_info *info = platform_get_drvdata(dev);
972 struct mfd_cell *cell = dev->dev.platform_data;
973 int retval;
974
975 acquire_console_sem();
976
977 if (cell->resume) {
978 retval = cell->resume(dev);
979 if (retval)
980 goto out;
981 }
982
983 tmiofb_irq(-1, info);
984
985 tmiofb_hw_init(dev);
986
987 tmiofb_hw_mode(dev);
988
989 fb_set_suspend(info, 0);
990out:
991 release_console_sem();
992 return retval;
993}
994#else
995#define tmiofb_suspend NULL
996#define tmiofb_resume NULL
997#endif
998
999static struct platform_driver tmiofb_driver = {
1000 .driver.name = "tmio-fb",
1001 .driver.owner = THIS_MODULE,
1002 .probe = tmiofb_probe,
1003 .remove = __devexit_p(tmiofb_remove),
1004 .suspend = tmiofb_suspend,
1005 .resume = tmiofb_resume,
1006};
1007
1008/*--------------------------------------------------------------------------*/
1009
1010#ifndef MODULE
1011static void __init tmiofb_setup(char *options)
1012{
1013 char *this_opt;
1014
1015 if (!options || !*options)
1016 return;
1017
1018 while ((this_opt = strsep(&options, ",")) != NULL) {
1019 if (!*this_opt)
1020 continue;
1021 /*
1022 * FIXME
1023 */
1024 }
1025}
1026#endif
1027
1028static int __init tmiofb_init(void)
1029{
1030#ifndef MODULE
1031 char *option = NULL;
1032
1033 if (fb_get_options("tmiofb", &option))
1034 return -ENODEV;
1035 tmiofb_setup(option);
1036#endif
1037 return platform_driver_register(&tmiofb_driver);
1038}
1039
1040static void __exit tmiofb_cleanup(void)
1041{
1042 platform_driver_unregister(&tmiofb_driver);
1043}
1044
1045module_init(tmiofb_init);
1046module_exit(tmiofb_cleanup);
1047
1048MODULE_DESCRIPTION("TMIO framebuffer driver");
1049MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
1050MODULE_LICENSE("GPL");
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index beefab2992c0..479b2e79ad68 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Frame buffer driver for Trident Blade and Image series 2 * Frame buffer driver for Trident TGUI, Blade and Image series
3 * 3 *
4 * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> 4 * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro>
5 * 5 *
@@ -13,7 +13,6 @@
13 * code, suggestions 13 * code, suggestions
14 * TODO: 14 * TODO:
15 * timing value tweaking so it looks good on every monitor in every mode 15 * timing value tweaking so it looks good on every monitor in every mode
16 * TGUI acceleration
17 */ 16 */
18 17
19#include <linux/module.h> 18#include <linux/module.h>
@@ -22,25 +21,26 @@
22#include <linux/pci.h> 21#include <linux/pci.h>
23 22
24#include <linux/delay.h> 23#include <linux/delay.h>
24#include <video/vga.h>
25#include <video/trident.h> 25#include <video/trident.h>
26 26
27#define VERSION "0.7.8-NEWAPI"
28
29struct tridentfb_par { 27struct tridentfb_par {
30 void __iomem *io_virt; /* iospace virtual memory address */ 28 void __iomem *io_virt; /* iospace virtual memory address */
29 u32 pseudo_pal[16];
30 int chip_id;
31 int flatpanel;
32 void (*init_accel) (struct tridentfb_par *, int, int);
33 void (*wait_engine) (struct tridentfb_par *);
34 void (*fill_rect)
35 (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
36 void (*copy_rect)
37 (struct tridentfb_par *par, u32, u32, u32, u32, u32, u32);
38 void (*image_blit)
39 (struct tridentfb_par *par, const char*,
40 u32, u32, u32, u32, u32, u32);
41 unsigned char eng_oper; /* engine operation... */
31}; 42};
32 43
33static unsigned char eng_oper; /* engine operation... */
34static struct fb_ops tridentfb_ops;
35
36static struct tridentfb_par default_par;
37
38/* FIXME:kmalloc these 3 instead */
39static struct fb_info fb_info;
40static u32 pseudo_pal[16];
41
42static struct fb_var_screeninfo default_var;
43
44static struct fb_fix_screeninfo tridentfb_fix = { 44static struct fb_fix_screeninfo tridentfb_fix = {
45 .id = "Trident", 45 .id = "Trident",
46 .type = FB_TYPE_PACKED_PIXELS, 46 .type = FB_TYPE_PACKED_PIXELS,
@@ -49,27 +49,22 @@ static struct fb_fix_screeninfo tridentfb_fix = {
49 .accel = FB_ACCEL_NONE, 49 .accel = FB_ACCEL_NONE,
50}; 50};
51 51
52static int chip_id;
53
54static int defaultaccel;
55static int displaytype;
56
57/* defaults which are normally overriden by user values */ 52/* defaults which are normally overriden by user values */
58 53
59/* video mode */ 54/* video mode */
60static char *mode_option __devinitdata = "640x480"; 55static char *mode_option __devinitdata = "640x480-8@60";
61static int bpp = 8; 56static int bpp __devinitdata = 8;
62 57
63static int noaccel; 58static int noaccel __devinitdata;
64 59
65static int center; 60static int center;
66static int stretch; 61static int stretch;
67 62
68static int fp; 63static int fp __devinitdata;
69static int crt; 64static int crt __devinitdata;
70 65
71static int memsize; 66static int memsize __devinitdata;
72static int memdiff; 67static int memdiff __devinitdata;
73static int nativex; 68static int nativex;
74 69
75module_param(mode_option, charp, 0); 70module_param(mode_option, charp, 0);
@@ -84,25 +79,53 @@ module_param(memsize, int, 0);
84module_param(memdiff, int, 0); 79module_param(memdiff, int, 0);
85module_param(nativex, int, 0); 80module_param(nativex, int, 0);
86module_param(fp, int, 0); 81module_param(fp, int, 0);
82MODULE_PARM_DESC(fp, "Define if flatpanel is connected");
87module_param(crt, int, 0); 83module_param(crt, int, 0);
84MODULE_PARM_DESC(crt, "Define if CRT is connected");
85
86static inline int is_oldclock(int id)
87{
88 return (id == TGUI9440) ||
89 (id == TGUI9660) ||
90 (id == CYBER9320);
91}
92
93static inline int is_oldprotect(int id)
94{
95 return is_oldclock(id) ||
96 (id == PROVIDIA9685) ||
97 (id == CYBER9382) ||
98 (id == CYBER9385);
99}
100
101static inline int is_blade(int id)
102{
103 return (id == BLADE3D) ||
104 (id == CYBERBLADEE4) ||
105 (id == CYBERBLADEi7) ||
106 (id == CYBERBLADEi7D) ||
107 (id == CYBERBLADEi1) ||
108 (id == CYBERBLADEi1D) ||
109 (id == CYBERBLADEAi1) ||
110 (id == CYBERBLADEAi1D);
111}
88 112
89static int chip3D; 113static inline int is_xp(int id)
90static int chipcyber; 114{
115 return (id == CYBERBLADEXPAi1) ||
116 (id == CYBERBLADEXPm8) ||
117 (id == CYBERBLADEXPm16);
118}
91 119
92static int is3Dchip(int id) 120static inline int is3Dchip(int id)
93{ 121{
94 return ((id == BLADE3D) || (id == CYBERBLADEE4) || 122 return is_blade(id) || is_xp(id) ||
95 (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
96 (id == CYBER9397) || (id == CYBER9397DVD) || 123 (id == CYBER9397) || (id == CYBER9397DVD) ||
97 (id == CYBER9520) || (id == CYBER9525DVD) || 124 (id == CYBER9520) || (id == CYBER9525DVD) ||
98 (id == IMAGE975) || (id == IMAGE985) || 125 (id == IMAGE975) || (id == IMAGE985);
99 (id == CYBERBLADEi1) || (id == CYBERBLADEi1D) ||
100 (id == CYBERBLADEAi1) || (id == CYBERBLADEAi1D) ||
101 (id == CYBERBLADEXPm8) || (id == CYBERBLADEXPm16) ||
102 (id == CYBERBLADEXPAi1));
103} 126}
104 127
105static int iscyber(int id) 128static inline int iscyber(int id)
106{ 129{
107 switch (id) { 130 switch (id) {
108 case CYBER9388: 131 case CYBER9388:
@@ -122,12 +145,7 @@ static int iscyber(int id)
122 return 1; 145 return 1;
123 146
124 case CYBER9320: 147 case CYBER9320:
125 case TGUI9660:
126 case IMAGE975:
127 case IMAGE985:
128 case BLADE3D:
129 case CYBERBLADEi7: /* VIA MPV4 integrated version */ 148 case CYBERBLADEi7: /* VIA MPV4 integrated version */
130
131 default: 149 default:
132 /* case CYBERBLDAEXPm8: Strange */ 150 /* case CYBERBLDAEXPm8: Strange */
133 /* case CYBERBLDAEXPm16: Strange */ 151 /* case CYBERBLDAEXPm16: Strange */
@@ -135,147 +153,110 @@ static int iscyber(int id)
135 } 153 }
136} 154}
137 155
138#define CRT 0x3D0 /* CRTC registers offset for color display */ 156static inline void t_outb(struct tridentfb_par *p, u8 val, u16 reg)
139 157{
140#ifndef TRIDENT_MMIO 158 fb_writeb(val, p->io_virt + reg);
141 #define TRIDENT_MMIO 1 159}
142#endif
143
144#if TRIDENT_MMIO
145 #define t_outb(val, reg) writeb(val,((struct tridentfb_par *)(fb_info.par))->io_virt + reg)
146 #define t_inb(reg) readb(((struct tridentfb_par*)(fb_info.par))->io_virt + reg)
147#else
148 #define t_outb(val, reg) outb(val, reg)
149 #define t_inb(reg) inb(reg)
150#endif
151 160
161static inline u8 t_inb(struct tridentfb_par *p, u16 reg)
162{
163 return fb_readb(p->io_virt + reg);
164}
152 165
153static struct accel_switch { 166static inline void writemmr(struct tridentfb_par *par, u16 r, u32 v)
154 void (*init_accel) (int, int); 167{
155 void (*wait_engine) (void); 168 fb_writel(v, par->io_virt + r);
156 void (*fill_rect) (u32, u32, u32, u32, u32, u32); 169}
157 void (*copy_rect) (u32, u32, u32, u32, u32, u32);
158} *acc;
159 170
160#define writemmr(r, v) writel(v, ((struct tridentfb_par *)fb_info.par)->io_virt + r) 171static inline u32 readmmr(struct tridentfb_par *par, u16 r)
161#define readmmr(r) readl(((struct tridentfb_par *)fb_info.par)->io_virt + r) 172{
173 return fb_readl(par->io_virt + r);
174}
162 175
163/* 176/*
164 * Blade specific acceleration. 177 * Blade specific acceleration.
165 */ 178 */
166 179
167#define point(x, y) ((y) << 16 | (x)) 180#define point(x, y) ((y) << 16 | (x))
168#define STA 0x2120 181
169#define CMD 0x2144 182static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp)
170#define ROP 0x2148
171#define CLR 0x2160
172#define SR1 0x2100
173#define SR2 0x2104
174#define DR1 0x2108
175#define DR2 0x210C
176
177#define ROP_S 0xCC
178
179static void blade_init_accel(int pitch, int bpp)
180{ 183{
181 int v1 = (pitch >> 3) << 20; 184 int v1 = (pitch >> 3) << 20;
182 int tmp = 0, v2; 185 int tmp = bpp == 24 ? 2 : (bpp >> 4);
183 switch (bpp) { 186 int v2 = v1 | (tmp << 29);
184 case 8: 187
185 tmp = 0; 188 writemmr(par, 0x21C0, v2);
186 break; 189 writemmr(par, 0x21C4, v2);
187 case 15: 190 writemmr(par, 0x21B8, v2);
188 tmp = 5; 191 writemmr(par, 0x21BC, v2);
189 break; 192 writemmr(par, 0x21D0, v1);
190 case 16: 193 writemmr(par, 0x21D4, v1);
191 tmp = 1; 194 writemmr(par, 0x21C8, v1);
192 break; 195 writemmr(par, 0x21CC, v1);
193 case 24: 196 writemmr(par, 0x216C, 0);
194 case 32:
195 tmp = 2;
196 break;
197 }
198 v2 = v1 | (tmp << 29);
199 writemmr(0x21C0, v2);
200 writemmr(0x21C4, v2);
201 writemmr(0x21B8, v2);
202 writemmr(0x21BC, v2);
203 writemmr(0x21D0, v1);
204 writemmr(0x21D4, v1);
205 writemmr(0x21C8, v1);
206 writemmr(0x21CC, v1);
207 writemmr(0x216C, 0);
208} 197}
209 198
210static void blade_wait_engine(void) 199static void blade_wait_engine(struct tridentfb_par *par)
211{ 200{
212 while (readmmr(STA) & 0xFA800000) ; 201 while (readmmr(par, STATUS) & 0xFA800000)
202 cpu_relax();
213} 203}
214 204
215static void blade_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) 205static void blade_fill_rect(struct tridentfb_par *par,
206 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
216{ 207{
217 writemmr(CLR, c); 208 writemmr(par, COLOR, c);
218 writemmr(ROP, rop ? 0x66 : ROP_S); 209 writemmr(par, ROP, rop ? ROP_X : ROP_S);
219 writemmr(CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); 210 writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
220 211
221 writemmr(DR1, point(x, y)); 212 writemmr(par, DST1, point(x, y));
222 writemmr(DR2, point(x + w - 1, y + h - 1)); 213 writemmr(par, DST2, point(x + w - 1, y + h - 1));
223} 214}
224 215
225static void blade_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) 216static void blade_image_blit(struct tridentfb_par *par, const char *data,
217 u32 x, u32 y, u32 w, u32 h, u32 c, u32 b)
218{
219 unsigned size = ((w + 31) >> 5) * h;
220
221 writemmr(par, COLOR, c);
222 writemmr(par, BGCOLOR, b);
223 writemmr(par, CMD, 0xa0000000 | 3 << 19);
224
225 writemmr(par, DST1, point(x, y));
226 writemmr(par, DST2, point(x + w - 1, y + h - 1));
227
228 memcpy(par->io_virt + 0x10000, data, 4 * size);
229}
230
231static void blade_copy_rect(struct tridentfb_par *par,
232 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
226{ 233{
227 u32 s1, s2, d1, d2;
228 int direction = 2; 234 int direction = 2;
229 s1 = point(x1, y1); 235 u32 s1 = point(x1, y1);
230 s2 = point(x1 + w - 1, y1 + h - 1); 236 u32 s2 = point(x1 + w - 1, y1 + h - 1);
231 d1 = point(x2, y2); 237 u32 d1 = point(x2, y2);
232 d2 = point(x2 + w - 1, y2 + h - 1); 238 u32 d2 = point(x2 + w - 1, y2 + h - 1);
233 239
234 if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) 240 if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
235 direction = 0; 241 direction = 0;
236 242
237 writemmr(ROP, ROP_S); 243 writemmr(par, ROP, ROP_S);
238 writemmr(CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction); 244 writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
239 245
240 writemmr(SR1, direction ? s2 : s1); 246 writemmr(par, SRC1, direction ? s2 : s1);
241 writemmr(SR2, direction ? s1 : s2); 247 writemmr(par, SRC2, direction ? s1 : s2);
242 writemmr(DR1, direction ? d2 : d1); 248 writemmr(par, DST1, direction ? d2 : d1);
243 writemmr(DR2, direction ? d1 : d2); 249 writemmr(par, DST2, direction ? d1 : d2);
244} 250}
245 251
246static struct accel_switch accel_blade = {
247 blade_init_accel,
248 blade_wait_engine,
249 blade_fill_rect,
250 blade_copy_rect,
251};
252
253/* 252/*
254 * BladeXP specific acceleration functions 253 * BladeXP specific acceleration functions
255 */ 254 */
256 255
257#define ROP_P 0xF0 256static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp)
258#define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff))
259
260static void xp_init_accel(int pitch, int bpp)
261{ 257{
262 int tmp = 0, v1; 258 unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
263 unsigned char x = 0; 259 int v1 = pitch << (bpp == 24 ? 20 : (18 + x));
264
265 switch (bpp) {
266 case 8:
267 x = 0;
268 break;
269 case 16:
270 x = 1;
271 break;
272 case 24:
273 x = 3;
274 break;
275 case 32:
276 x = 2;
277 break;
278 }
279 260
280 switch (pitch << (bpp >> 3)) { 261 switch (pitch << (bpp >> 3)) {
281 case 8192: 262 case 8192:
@@ -293,42 +274,21 @@ static void xp_init_accel(int pitch, int bpp)
293 break; 274 break;
294 } 275 }
295 276
296 t_outb(x, 0x2125); 277 t_outb(par, x, 0x2125);
297
298 eng_oper = x | 0x40;
299
300 switch (bpp) {
301 case 8:
302 tmp = 18;
303 break;
304 case 15:
305 case 16:
306 tmp = 19;
307 break;
308 case 24:
309 case 32:
310 tmp = 20;
311 break;
312 }
313 278
314 v1 = pitch << tmp; 279 par->eng_oper = x | 0x40;
315 280
316 writemmr(0x2154, v1); 281 writemmr(par, 0x2154, v1);
317 writemmr(0x2150, v1); 282 writemmr(par, 0x2150, v1);
318 t_outb(3, 0x2126); 283 t_outb(par, 3, 0x2126);
319} 284}
320 285
321static void xp_wait_engine(void) 286static void xp_wait_engine(struct tridentfb_par *par)
322{ 287{
323 int busy; 288 int count = 0;
324 int count, timeout; 289 int timeout = 0;
325 290
326 count = 0; 291 while (t_inb(par, STATUS) & 0x80) {
327 timeout = 0;
328 for (;;) {
329 busy = t_inb(STA) & 0x80;
330 if (busy != 0x80)
331 return;
332 count++; 292 count++;
333 if (count == 10000000) { 293 if (count == 10000000) {
334 /* Timeout */ 294 /* Timeout */
@@ -336,30 +296,31 @@ static void xp_wait_engine(void)
336 timeout++; 296 timeout++;
337 if (timeout == 8) { 297 if (timeout == 8) {
338 /* Reset engine */ 298 /* Reset engine */
339 t_outb(0x00, 0x2120); 299 t_outb(par, 0x00, STATUS);
340 return; 300 return;
341 } 301 }
342 } 302 }
303 cpu_relax();
343 } 304 }
344} 305}
345 306
346static void xp_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) 307static void xp_fill_rect(struct tridentfb_par *par,
308 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
347{ 309{
348 writemmr(0x2127, ROP_P); 310 writemmr(par, 0x2127, ROP_P);
349 writemmr(0x2158, c); 311 writemmr(par, 0x2158, c);
350 writemmr(0x2128, 0x4000); 312 writemmr(par, DRAWFL, 0x4000);
351 writemmr(0x2140, masked_point(h, w)); 313 writemmr(par, OLDDIM, point(h, w));
352 writemmr(0x2138, masked_point(y, x)); 314 writemmr(par, OLDDST, point(y, x));
353 t_outb(0x01, 0x2124); 315 t_outb(par, 0x01, OLDCMD);
354 t_outb(eng_oper, 0x2125); 316 t_outb(par, par->eng_oper, 0x2125);
355} 317}
356 318
357static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) 319static void xp_copy_rect(struct tridentfb_par *par,
320 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
358{ 321{
359 int direction;
360 u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp; 322 u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
361 323 int direction = 0x0004;
362 direction = 0x0004;
363 324
364 if ((x1 < x2) && (y1 == y2)) { 325 if ((x1 < x2) && (y1 == y2)) {
365 direction |= 0x0200; 326 direction |= 0x0200;
@@ -379,103 +340,152 @@ static void xp_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
379 y2_tmp = y2; 340 y2_tmp = y2;
380 } 341 }
381 342
382 writemmr(0x2128, direction); 343 writemmr(par, DRAWFL, direction);
383 t_outb(ROP_S, 0x2127); 344 t_outb(par, ROP_S, 0x2127);
384 writemmr(0x213C, masked_point(y1_tmp, x1_tmp)); 345 writemmr(par, OLDSRC, point(y1_tmp, x1_tmp));
385 writemmr(0x2138, masked_point(y2_tmp, x2_tmp)); 346 writemmr(par, OLDDST, point(y2_tmp, x2_tmp));
386 writemmr(0x2140, masked_point(h, w)); 347 writemmr(par, OLDDIM, point(h, w));
387 t_outb(0x01, 0x2124); 348 t_outb(par, 0x01, OLDCMD);
388} 349}
389 350
390static struct accel_switch accel_xp = {
391 xp_init_accel,
392 xp_wait_engine,
393 xp_fill_rect,
394 xp_copy_rect,
395};
396
397/* 351/*
398 * Image specific acceleration functions 352 * Image specific acceleration functions
399 */ 353 */
400static void image_init_accel(int pitch, int bpp) 354static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp)
401{ 355{
402 int tmp = 0; 356 int tmp = bpp == 24 ? 2: (bpp >> 4);
403 switch (bpp) { 357
404 case 8: 358 writemmr(par, 0x2120, 0xF0000000);
405 tmp = 0; 359 writemmr(par, 0x2120, 0x40000000 | tmp);
406 break; 360 writemmr(par, 0x2120, 0x80000000);
407 case 15: 361 writemmr(par, 0x2144, 0x00000000);
408 tmp = 5; 362 writemmr(par, 0x2148, 0x00000000);
409 break; 363 writemmr(par, 0x2150, 0x00000000);
410 case 16: 364 writemmr(par, 0x2154, 0x00000000);
411 tmp = 1; 365 writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
412 break; 366 writemmr(par, 0x216C, 0x00000000);
413 case 24: 367 writemmr(par, 0x2170, 0x00000000);
414 case 32: 368 writemmr(par, 0x217C, 0x00000000);
415 tmp = 2; 369 writemmr(par, 0x2120, 0x10000000);
416 break; 370 writemmr(par, 0x2130, (2047 << 16) | 2047);
417 }
418 writemmr(0x2120, 0xF0000000);
419 writemmr(0x2120, 0x40000000 | tmp);
420 writemmr(0x2120, 0x80000000);
421 writemmr(0x2144, 0x00000000);
422 writemmr(0x2148, 0x00000000);
423 writemmr(0x2150, 0x00000000);
424 writemmr(0x2154, 0x00000000);
425 writemmr(0x2120, 0x60000000 | (pitch << 16) | pitch);
426 writemmr(0x216C, 0x00000000);
427 writemmr(0x2170, 0x00000000);
428 writemmr(0x217C, 0x00000000);
429 writemmr(0x2120, 0x10000000);
430 writemmr(0x2130, (2047 << 16) | 2047);
431} 371}
432 372
433static void image_wait_engine(void) 373static void image_wait_engine(struct tridentfb_par *par)
434{ 374{
435 while (readmmr(0x2164) & 0xF0000000) ; 375 while (readmmr(par, 0x2164) & 0xF0000000)
376 cpu_relax();
436} 377}
437 378
438static void image_fill_rect(u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) 379static void image_fill_rect(struct tridentfb_par *par,
380 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
439{ 381{
440 writemmr(0x2120, 0x80000000); 382 writemmr(par, 0x2120, 0x80000000);
441 writemmr(0x2120, 0x90000000 | ROP_S); 383 writemmr(par, 0x2120, 0x90000000 | ROP_S);
442 384
443 writemmr(0x2144, c); 385 writemmr(par, 0x2144, c);
444 386
445 writemmr(DR1, point(x, y)); 387 writemmr(par, DST1, point(x, y));
446 writemmr(DR2, point(x + w - 1, y + h - 1)); 388 writemmr(par, DST2, point(x + w - 1, y + h - 1));
447 389
448 writemmr(0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9); 390 writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
449} 391}
450 392
451static void image_copy_rect(u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) 393static void image_copy_rect(struct tridentfb_par *par,
394 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
452{ 395{
453 u32 s1, s2, d1, d2; 396 int direction = 0x4;
454 int direction = 2; 397 u32 s1 = point(x1, y1);
455 s1 = point(x1, y1); 398 u32 s2 = point(x1 + w - 1, y1 + h - 1);
456 s2 = point(x1 + w - 1, y1 + h - 1); 399 u32 d1 = point(x2, y2);
457 d1 = point(x2, y2); 400 u32 d2 = point(x2 + w - 1, y2 + h - 1);
458 d2 = point(x2 + w - 1, y2 + h - 1);
459 401
460 if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) 402 if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
461 direction = 0; 403 direction = 0;
462 404
463 writemmr(0x2120, 0x80000000); 405 writemmr(par, 0x2120, 0x80000000);
464 writemmr(0x2120, 0x90000000 | ROP_S); 406 writemmr(par, 0x2120, 0x90000000 | ROP_S);
465 407
466 writemmr(SR1, direction ? s2 : s1); 408 writemmr(par, SRC1, direction ? s2 : s1);
467 writemmr(SR2, direction ? s1 : s2); 409 writemmr(par, SRC2, direction ? s1 : s2);
468 writemmr(DR1, direction ? d2 : d1); 410 writemmr(par, DST1, direction ? d2 : d1);
469 writemmr(DR2, direction ? d1 : d2); 411 writemmr(par, DST2, direction ? d1 : d2);
470 writemmr(0x2124, 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction); 412 writemmr(par, 0x2124,
413 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
471} 414}
472 415
473static struct accel_switch accel_image = { 416/*
474 image_init_accel, 417 * TGUI 9440/96XX acceleration
475 image_wait_engine, 418 */
476 image_fill_rect, 419
477 image_copy_rect, 420static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp)
478}; 421{
422 unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
423
424 /* disable clipping */
425 writemmr(par, 0x2148, 0);
426 writemmr(par, 0x214C, point(4095, 2047));
427
428 switch ((pitch * bpp) / 8) {
429 case 8192:
430 case 512:
431 x |= 0x00;
432 break;
433 case 1024:
434 x |= 0x04;
435 break;
436 case 2048:
437 x |= 0x08;
438 break;
439 case 4096:
440 x |= 0x0C;
441 break;
442 }
443
444 fb_writew(x, par->io_virt + 0x2122);
445}
446
447static void tgui_fill_rect(struct tridentfb_par *par,
448 u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop)
449{
450 t_outb(par, ROP_P, 0x2127);
451 writemmr(par, OLDCLR, c);
452 writemmr(par, DRAWFL, 0x4020);
453 writemmr(par, OLDDIM, point(w - 1, h - 1));
454 writemmr(par, OLDDST, point(x, y));
455 t_outb(par, 1, OLDCMD);
456}
457
458static void tgui_copy_rect(struct tridentfb_par *par,
459 u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h)
460{
461 int flags = 0;
462 u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
463
464 if ((x1 < x2) && (y1 == y2)) {
465 flags |= 0x0200;
466 x1_tmp = x1 + w - 1;
467 x2_tmp = x2 + w - 1;
468 } else {
469 x1_tmp = x1;
470 x2_tmp = x2;
471 }
472
473 if (y1 < y2) {
474 flags |= 0x0100;
475 y1_tmp = y1 + h - 1;
476 y2_tmp = y2 + h - 1;
477 } else {
478 y1_tmp = y1;
479 y2_tmp = y2;
480 }
481
482 writemmr(par, DRAWFL, 0x4 | flags);
483 t_outb(par, ROP_S, 0x2127);
484 writemmr(par, OLDSRC, point(x1_tmp, y1_tmp));
485 writemmr(par, OLDDST, point(x2_tmp, y2_tmp));
486 writemmr(par, OLDDIM, point(w - 1, h - 1));
487 t_outb(par, 1, OLDCMD);
488}
479 489
480/* 490/*
481 * Accel functions called by the upper layers 491 * Accel functions called by the upper layers
@@ -484,129 +494,162 @@ static struct accel_switch accel_image = {
484static void tridentfb_fillrect(struct fb_info *info, 494static void tridentfb_fillrect(struct fb_info *info,
485 const struct fb_fillrect *fr) 495 const struct fb_fillrect *fr)
486{ 496{
487 int bpp = info->var.bits_per_pixel; 497 struct tridentfb_par *par = info->par;
488 int col = 0; 498 int col;
489 499
490 switch (bpp) { 500 if (info->flags & FBINFO_HWACCEL_DISABLED) {
491 default: 501 cfb_fillrect(info, fr);
492 case 8: 502 return;
493 col |= fr->color; 503 }
504 if (info->var.bits_per_pixel == 8) {
505 col = fr->color;
494 col |= col << 8; 506 col |= col << 8;
495 col |= col << 16; 507 col |= col << 16;
496 break; 508 } else
497 case 16:
498 col = ((u32 *)(info->pseudo_palette))[fr->color]; 509 col = ((u32 *)(info->pseudo_palette))[fr->color];
499 break; 510
500 case 32: 511 par->wait_engine(par);
501 col = ((u32 *)(info->pseudo_palette))[fr->color]; 512 par->fill_rect(par, fr->dx, fr->dy, fr->width,
502 break; 513 fr->height, col, fr->rop);
514}
515
516static void tridentfb_imageblit(struct fb_info *info,
517 const struct fb_image *img)
518{
519 struct tridentfb_par *par = info->par;
520 int col, bgcol;
521
522 if ((info->flags & FBINFO_HWACCEL_DISABLED) || img->depth != 1) {
523 cfb_imageblit(info, img);
524 return;
525 }
526 if (info->var.bits_per_pixel == 8) {
527 col = img->fg_color;
528 col |= col << 8;
529 col |= col << 16;
530 bgcol = img->bg_color;
531 bgcol |= bgcol << 8;
532 bgcol |= bgcol << 16;
533 } else {
534 col = ((u32 *)(info->pseudo_palette))[img->fg_color];
535 bgcol = ((u32 *)(info->pseudo_palette))[img->bg_color];
503 } 536 }
504 537
505 acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop); 538 par->wait_engine(par);
506 acc->wait_engine(); 539 if (par->image_blit)
540 par->image_blit(par, img->data, img->dx, img->dy,
541 img->width, img->height, col, bgcol);
542 else
543 cfb_imageblit(info, img);
507} 544}
545
508static void tridentfb_copyarea(struct fb_info *info, 546static void tridentfb_copyarea(struct fb_info *info,
509 const struct fb_copyarea *ca) 547 const struct fb_copyarea *ca)
510{ 548{
511 acc->copy_rect(ca->sx, ca->sy, ca->dx, ca->dy, ca->width, ca->height); 549 struct tridentfb_par *par = info->par;
512 acc->wait_engine(); 550
551 if (info->flags & FBINFO_HWACCEL_DISABLED) {
552 cfb_copyarea(info, ca);
553 return;
554 }
555 par->wait_engine(par);
556 par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy,
557 ca->width, ca->height);
558}
559
560static int tridentfb_sync(struct fb_info *info)
561{
562 struct tridentfb_par *par = info->par;
563
564 if (!(info->flags & FBINFO_HWACCEL_DISABLED))
565 par->wait_engine(par);
566 return 0;
513} 567}
514#else /* !CONFIG_FB_TRIDENT_ACCEL */ 568#else
515#define tridentfb_fillrect cfb_fillrect 569#define tridentfb_fillrect cfb_fillrect
516#define tridentfb_copyarea cfb_copyarea 570#define tridentfb_copyarea cfb_copyarea
571#define tridentfb_imageblit cfb_imageblit
517#endif /* CONFIG_FB_TRIDENT_ACCEL */ 572#endif /* CONFIG_FB_TRIDENT_ACCEL */
518 573
519
520/* 574/*
521 * Hardware access functions 575 * Hardware access functions
522 */ 576 */
523 577
524static inline unsigned char read3X4(int reg) 578static inline unsigned char read3X4(struct tridentfb_par *par, int reg)
525{ 579{
526 struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par; 580 return vga_mm_rcrt(par->io_virt, reg);
527 writeb(reg, par->io_virt + CRT + 4);
528 return readb(par->io_virt + CRT + 5);
529} 581}
530 582
531static inline void write3X4(int reg, unsigned char val) 583static inline void write3X4(struct tridentfb_par *par, int reg,
584 unsigned char val)
532{ 585{
533 struct tridentfb_par *par = (struct tridentfb_par *)fb_info.par; 586 vga_mm_wcrt(par->io_virt, reg, val);
534 writeb(reg, par->io_virt + CRT + 4);
535 writeb(val, par->io_virt + CRT + 5);
536} 587}
537 588
538static inline unsigned char read3C4(int reg) 589static inline unsigned char read3CE(struct tridentfb_par *par,
590 unsigned char reg)
539{ 591{
540 t_outb(reg, 0x3C4); 592 return vga_mm_rgfx(par->io_virt, reg);
541 return t_inb(0x3C5);
542} 593}
543 594
544static inline void write3C4(int reg, unsigned char val) 595static inline void writeAttr(struct tridentfb_par *par, int reg,
596 unsigned char val)
545{ 597{
546 t_outb(reg, 0x3C4); 598 fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */
547 t_outb(val, 0x3C5); 599 vga_mm_wattr(par->io_virt, reg, val);
548} 600}
549 601
550static inline unsigned char read3CE(int reg) 602static inline void write3CE(struct tridentfb_par *par, int reg,
603 unsigned char val)
551{ 604{
552 t_outb(reg, 0x3CE); 605 vga_mm_wgfx(par->io_virt, reg, val);
553 return t_inb(0x3CF);
554} 606}
555 607
556static inline void writeAttr(int reg, unsigned char val) 608static void enable_mmio(struct tridentfb_par *par)
557{
558 readb(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); /* flip-flop to index */
559 t_outb(reg, 0x3C0);
560 t_outb(val, 0x3C0);
561}
562
563static inline void write3CE(int reg, unsigned char val)
564{
565 t_outb(reg, 0x3CE);
566 t_outb(val, 0x3CF);
567}
568
569static void enable_mmio(void)
570{ 609{
571 /* Goto New Mode */ 610 /* Goto New Mode */
572 outb(0x0B, 0x3C4); 611 vga_io_rseq(0x0B);
573 inb(0x3C5);
574 612
575 /* Unprotect registers */ 613 /* Unprotect registers */
576 outb(NewMode1, 0x3C4); 614 vga_io_wseq(NewMode1, 0x80);
577 outb(0x80, 0x3C5); 615 if (!is_oldprotect(par->chip_id))
616 vga_io_wseq(Protection, 0x92);
578 617
579 /* Enable MMIO */ 618 /* Enable MMIO */
580 outb(PCIReg, 0x3D4); 619 outb(PCIReg, 0x3D4);
581 outb(inb(0x3D5) | 0x01, 0x3D5); 620 outb(inb(0x3D5) | 0x01, 0x3D5);
582} 621}
583 622
584static void disable_mmio(void) 623static void disable_mmio(struct tridentfb_par *par)
585{ 624{
586 /* Goto New Mode */ 625 /* Goto New Mode */
587 t_outb(0x0B, 0x3C4); 626 vga_mm_rseq(par->io_virt, 0x0B);
588 t_inb(0x3C5);
589 627
590 /* Unprotect registers */ 628 /* Unprotect registers */
591 t_outb(NewMode1, 0x3C4); 629 vga_mm_wseq(par->io_virt, NewMode1, 0x80);
592 t_outb(0x80, 0x3C5); 630 if (!is_oldprotect(par->chip_id))
631 vga_mm_wseq(par->io_virt, Protection, 0x92);
593 632
594 /* Disable MMIO */ 633 /* Disable MMIO */
595 t_outb(PCIReg, 0x3D4); 634 t_outb(par, PCIReg, 0x3D4);
596 t_outb(t_inb(0x3D5) & ~0x01, 0x3D5); 635 t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
597} 636}
598 637
599#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F) 638static inline void crtc_unlock(struct tridentfb_par *par)
639{
640 write3X4(par, VGA_CRTC_V_SYNC_END,
641 read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);
642}
600 643
601/* Return flat panel's maximum x resolution */ 644/* Return flat panel's maximum x resolution */
602static int __devinit get_nativex(void) 645static int __devinit get_nativex(struct tridentfb_par *par)
603{ 646{
604 int x, y, tmp; 647 int x, y, tmp;
605 648
606 if (nativex) 649 if (nativex)
607 return nativex; 650 return nativex;
608 651
609 tmp = (read3CE(VertStretch) >> 4) & 3; 652 tmp = (read3CE(par, VertStretch) >> 4) & 3;
610 653
611 switch (tmp) { 654 switch (tmp) {
612 case 0: 655 case 0:
@@ -632,77 +675,92 @@ static int __devinit get_nativex(void)
632} 675}
633 676
634/* Set pitch */ 677/* Set pitch */
635static void set_lwidth(int width) 678static inline void set_lwidth(struct tridentfb_par *par, int width)
636{ 679{
637 write3X4(Offset, width & 0xFF); 680 write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
638 write3X4(AddColReg, 681 write3X4(par, AddColReg,
639 (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >> 4)); 682 (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
640} 683}
641 684
642/* For resolutions smaller than FP resolution stretch */ 685/* For resolutions smaller than FP resolution stretch */
643static void screen_stretch(void) 686static void screen_stretch(struct tridentfb_par *par)
644{ 687{
645 if (chip_id != CYBERBLADEXPAi1) 688 if (par->chip_id != CYBERBLADEXPAi1)
646 write3CE(BiosReg, 0); 689 write3CE(par, BiosReg, 0);
647 else 690 else
648 write3CE(BiosReg, 8); 691 write3CE(par, BiosReg, 8);
649 write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 1); 692 write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);
650 write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 1); 693 write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);
651} 694}
652 695
653/* For resolutions smaller than FP resolution center */ 696/* For resolutions smaller than FP resolution center */
654static void screen_center(void) 697static inline void screen_center(struct tridentfb_par *par)
655{ 698{
656 write3CE(VertStretch, (read3CE(VertStretch) & 0x7C) | 0x80); 699 write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);
657 write3CE(HorStretch, (read3CE(HorStretch) & 0x7C) | 0x80); 700 write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);
658} 701}
659 702
660/* Address of first shown pixel in display memory */ 703/* Address of first shown pixel in display memory */
661static void set_screen_start(int base) 704static void set_screen_start(struct tridentfb_par *par, int base)
662{ 705{
663 write3X4(StartAddrLow, base & 0xFF); 706 u8 tmp;
664 write3X4(StartAddrHigh, (base & 0xFF00) >> 8); 707 write3X4(par, VGA_CRTC_START_LO, base & 0xFF);
665 write3X4(CRTCModuleTest, 708 write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);
666 (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11)); 709 tmp = read3X4(par, CRTCModuleTest) & 0xDF;
667 write3X4(CRTHiOrd, 710 write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));
668 (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17)); 711 tmp = read3X4(par, CRTHiOrd) & 0xF8;
712 write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
669} 713}
670 714
671/* Set dotclock frequency */ 715/* Set dotclock frequency */
672static void set_vclk(unsigned long freq) 716static void set_vclk(struct tridentfb_par *par, unsigned long freq)
673{ 717{
674 int m, n, k; 718 int m, n, k;
675 unsigned long f, fi, d, di; 719 unsigned long fi, d, di;
676 unsigned char lo = 0, hi = 0; 720 unsigned char best_m = 0, best_n = 0, best_k = 0;
721 unsigned char hi, lo;
722 unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;
677 723
678 d = 20000; 724 d = 20000;
679 for (k = 2; k >= 0; k--) 725 for (k = shift; k >= 0; k--)
680 for (m = 0; m < 63; m++) 726 for (m = 1; m < 32; m++) {
681 for (n = 0; n < 128; n++) { 727 n = ((m + 2) << shift) - 8;
728 for (n = (n < 0 ? 0 : n); n < 122; n++) {
682 fi = ((14318l * (n + 8)) / (m + 2)) >> k; 729 fi = ((14318l * (n + 8)) / (m + 2)) >> k;
683 if ((di = abs(fi - freq)) < d) { 730 di = abs(fi - freq);
731 if (di < d || (di == d && k == best_k)) {
684 d = di; 732 d = di;
685 f = fi; 733 best_n = n;
686 lo = n; 734 best_m = m;
687 hi = (k << 6) | m; 735 best_k = k;
688 } 736 }
689 if (fi > freq) 737 if (fi > freq)
690 break; 738 break;
691 } 739 }
692 if (chip3D) { 740 }
693 write3C4(ClockHigh, hi); 741
694 write3C4(ClockLow, lo); 742 if (is_oldclock(par->chip_id)) {
743 lo = best_n | (best_m << 7);
744 hi = (best_m >> 1) | (best_k << 4);
695 } else { 745 } else {
696 outb(lo, 0x43C8); 746 lo = best_n;
697 outb(hi, 0x43C9); 747 hi = best_m | (best_k << 6);
748 }
749
750 if (is3Dchip(par->chip_id)) {
751 vga_mm_wseq(par->io_virt, ClockHigh, hi);
752 vga_mm_wseq(par->io_virt, ClockLow, lo);
753 } else {
754 t_outb(par, lo, 0x43C8);
755 t_outb(par, hi, 0x43C9);
698 } 756 }
699 debug("VCLK = %X %X\n", hi, lo); 757 debug("VCLK = %X %X\n", hi, lo);
700} 758}
701 759
702/* Set number of lines for flat panels*/ 760/* Set number of lines for flat panels*/
703static void set_number_of_lines(int lines) 761static void set_number_of_lines(struct tridentfb_par *par, int lines)
704{ 762{
705 int tmp = read3CE(CyberEnhance) & 0x8F; 763 int tmp = read3CE(par, CyberEnhance) & 0x8F;
706 if (lines > 1024) 764 if (lines > 1024)
707 tmp |= 0x50; 765 tmp |= 0x50;
708 else if (lines > 768) 766 else if (lines > 768)
@@ -711,24 +769,24 @@ static void set_number_of_lines(int lines)
711 tmp |= 0x20; 769 tmp |= 0x20;
712 else if (lines > 480) 770 else if (lines > 480)
713 tmp |= 0x10; 771 tmp |= 0x10;
714 write3CE(CyberEnhance, tmp); 772 write3CE(par, CyberEnhance, tmp);
715} 773}
716 774
717/* 775/*
718 * If we see that FP is active we assume we have one. 776 * If we see that FP is active we assume we have one.
719 * Otherwise we have a CRT display.User can override. 777 * Otherwise we have a CRT display. User can override.
720 */ 778 */
721static unsigned int __devinit get_displaytype(void) 779static int __devinit is_flatpanel(struct tridentfb_par *par)
722{ 780{
723 if (fp) 781 if (fp)
724 return DISPLAY_FP; 782 return 1;
725 if (crt || !chipcyber) 783 if (crt || !iscyber(par->chip_id))
726 return DISPLAY_CRT; 784 return 0;
727 return (read3CE(FPConfig) & 0x10) ? DISPLAY_FP : DISPLAY_CRT; 785 return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;
728} 786}
729 787
730/* Try detecting the video memory size */ 788/* Try detecting the video memory size */
731static unsigned int __devinit get_memsize(void) 789static unsigned int __devinit get_memsize(struct tridentfb_par *par)
732{ 790{
733 unsigned char tmp, tmp2; 791 unsigned char tmp, tmp2;
734 unsigned int k; 792 unsigned int k;
@@ -737,12 +795,12 @@ static unsigned int __devinit get_memsize(void)
737 if (memsize) 795 if (memsize)
738 k = memsize * Kb; 796 k = memsize * Kb;
739 else 797 else
740 switch (chip_id) { 798 switch (par->chip_id) {
741 case CYBER9525DVD: 799 case CYBER9525DVD:
742 k = 2560 * Kb; 800 k = 2560 * Kb;
743 break; 801 break;
744 default: 802 default:
745 tmp = read3X4(SPR) & 0x0F; 803 tmp = read3X4(par, SPR) & 0x0F;
746 switch (tmp) { 804 switch (tmp) {
747 805
748 case 0x01: 806 case 0x01:
@@ -774,7 +832,7 @@ static unsigned int __devinit get_memsize(void)
774 break; 832 break;
775 case 0x0E: /* XP */ 833 case 0x0E: /* XP */
776 834
777 tmp2 = read3C4(0xC1); 835 tmp2 = vga_mm_rseq(par->io_virt, 0xC1);
778 switch (tmp2) { 836 switch (tmp2) {
779 case 0x00: 837 case 0x00:
780 k = 20 * Mb; 838 k = 20 * Mb;
@@ -812,26 +870,67 @@ static unsigned int __devinit get_memsize(void)
812static int tridentfb_check_var(struct fb_var_screeninfo *var, 870static int tridentfb_check_var(struct fb_var_screeninfo *var,
813 struct fb_info *info) 871 struct fb_info *info)
814{ 872{
873 struct tridentfb_par *par = info->par;
815 int bpp = var->bits_per_pixel; 874 int bpp = var->bits_per_pixel;
875 int line_length;
876 int ramdac = 230000; /* 230MHz for most 3D chips */
816 debug("enter\n"); 877 debug("enter\n");
817 878
818 /* check color depth */ 879 /* check color depth */
819 if (bpp == 24) 880 if (bpp == 24)
820 bpp = var->bits_per_pixel = 32; 881 bpp = var->bits_per_pixel = 32;
882 if (bpp != 8 && bpp != 16 && bpp != 32)
883 return -EINVAL;
884 if (par->chip_id == TGUI9440 && bpp == 32)
885 return -EINVAL;
821 /* check whether resolution fits on panel and in memory */ 886 /* check whether resolution fits on panel and in memory */
822 if (flatpanel && nativex && var->xres > nativex) 887 if (par->flatpanel && nativex && var->xres > nativex)
888 return -EINVAL;
889 /* various resolution checks */
890 var->xres = (var->xres + 7) & ~0x7;
891 if (var->xres > var->xres_virtual)
892 var->xres_virtual = var->xres;
893 if (var->yres > var->yres_virtual)
894 var->yres_virtual = var->yres;
895 if (var->xres_virtual > 4095 || var->yres > 2048)
823 return -EINVAL; 896 return -EINVAL;
824 if (var->xres * var->yres_virtual * bpp / 8 > info->fix.smem_len) 897 /* prevent from position overflow for acceleration */
898 if (var->yres_virtual > 0xffff)
899 return -EINVAL;
900 line_length = var->xres_virtual * bpp / 8;
901
902 if (!is3Dchip(par->chip_id) &&
903 !(info->flags & FBINFO_HWACCEL_DISABLED)) {
904 /* acceleration requires line length to be power of 2 */
905 if (line_length <= 512)
906 var->xres_virtual = 512 * 8 / bpp;
907 else if (line_length <= 1024)
908 var->xres_virtual = 1024 * 8 / bpp;
909 else if (line_length <= 2048)
910 var->xres_virtual = 2048 * 8 / bpp;
911 else if (line_length <= 4096)
912 var->xres_virtual = 4096 * 8 / bpp;
913 else if (line_length <= 8192)
914 var->xres_virtual = 8192 * 8 / bpp;
915 else
916 return -EINVAL;
917
918 line_length = var->xres_virtual * bpp / 8;
919 }
920
921 /* datasheet specifies how to set panning only up to 4 MB */
922 if (line_length * (var->yres_virtual - var->yres) > (4 << 20))
923 var->yres_virtual = ((4 << 20) / line_length) + var->yres;
924
925 if (line_length * var->yres_virtual > info->fix.smem_len)
825 return -EINVAL; 926 return -EINVAL;
826 927
827 switch (bpp) { 928 switch (bpp) {
828 case 8: 929 case 8:
829 var->red.offset = 0; 930 var->red.offset = 0;
830 var->green.offset = 0; 931 var->red.length = 8;
831 var->blue.offset = 0; 932 var->green = var->red;
832 var->red.length = 6; 933 var->blue = var->red;
833 var->green.length = 6;
834 var->blue.length = 6;
835 break; 934 break;
836 case 16: 935 case 16:
837 var->red.offset = 11; 936 var->red.offset = 11;
@@ -852,6 +951,33 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
852 default: 951 default:
853 return -EINVAL; 952 return -EINVAL;
854 } 953 }
954
955 if (is_xp(par->chip_id))
956 ramdac = 350000;
957
958 switch (par->chip_id) {
959 case TGUI9440:
960 ramdac = (bpp >= 16) ? 45000 : 90000;
961 break;
962 case CYBER9320:
963 case TGUI9660:
964 ramdac = 135000;
965 break;
966 case PROVIDIA9685:
967 case CYBER9388:
968 case CYBER9382:
969 case CYBER9385:
970 ramdac = 170000;
971 break;
972 }
973
974 /* The clock is doubled for 32 bpp */
975 if (bpp == 32)
976 ramdac /= 2;
977
978 if (PICOS2KHZ(var->pixclock) > ramdac)
979 return -EINVAL;
980
855 debug("exit\n"); 981 debug("exit\n");
856 982
857 return 0; 983 return 0;
@@ -862,25 +988,31 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var,
862static int tridentfb_pan_display(struct fb_var_screeninfo *var, 988static int tridentfb_pan_display(struct fb_var_screeninfo *var,
863 struct fb_info *info) 989 struct fb_info *info)
864{ 990{
991 struct tridentfb_par *par = info->par;
865 unsigned int offset; 992 unsigned int offset;
866 993
867 debug("enter\n"); 994 debug("enter\n");
868 offset = (var->xoffset + (var->yoffset * var->xres)) 995 offset = (var->xoffset + (var->yoffset * var->xres_virtual))
869 * var->bits_per_pixel / 32; 996 * var->bits_per_pixel / 32;
870 info->var.xoffset = var->xoffset; 997 set_screen_start(par, offset);
871 info->var.yoffset = var->yoffset;
872 set_screen_start(offset);
873 debug("exit\n"); 998 debug("exit\n");
874 return 0; 999 return 0;
875} 1000}
876 1001
877#define shadowmode_on() write3CE(CyberControl, read3CE(CyberControl) | 0x81) 1002static inline void shadowmode_on(struct tridentfb_par *par)
878#define shadowmode_off() write3CE(CyberControl, read3CE(CyberControl) & 0x7E) 1003{
1004 write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);
1005}
1006
1007static inline void shadowmode_off(struct tridentfb_par *par)
1008{
1009 write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);
1010}
879 1011
880/* Set the hardware to the requested video mode */ 1012/* Set the hardware to the requested video mode */
881static int tridentfb_set_par(struct fb_info *info) 1013static int tridentfb_set_par(struct fb_info *info)
882{ 1014{
883 struct tridentfb_par *par = (struct tridentfb_par *)(info->par); 1015 struct tridentfb_par *par = info->par;
884 u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; 1016 u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
885 u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; 1017 u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
886 struct fb_var_screeninfo *var = &info->var; 1018 struct fb_var_screeninfo *var = &info->var;
@@ -891,58 +1023,73 @@ static int tridentfb_set_par(struct fb_info *info)
891 debug("enter\n"); 1023 debug("enter\n");
892 hdispend = var->xres / 8 - 1; 1024 hdispend = var->xres / 8 - 1;
893 hsyncstart = (var->xres + var->right_margin) / 8; 1025 hsyncstart = (var->xres + var->right_margin) / 8;
894 hsyncend = var->hsync_len / 8; 1026 hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;
895 htotal = 1027 htotal = (var->xres + var->left_margin + var->right_margin +
896 (var->xres + var->left_margin + var->right_margin + 1028 var->hsync_len) / 8 - 5;
897 var->hsync_len) / 8 - 10;
898 hblankstart = hdispend + 1; 1029 hblankstart = hdispend + 1;
899 hblankend = htotal + 5; 1030 hblankend = htotal + 3;
900 1031
901 vdispend = var->yres - 1; 1032 vdispend = var->yres - 1;
902 vsyncstart = var->yres + var->lower_margin; 1033 vsyncstart = var->yres + var->lower_margin;
903 vsyncend = var->vsync_len; 1034 vsyncend = vsyncstart + var->vsync_len;
904 vtotal = var->upper_margin + vsyncstart + vsyncend - 2; 1035 vtotal = var->upper_margin + vsyncend - 2;
905 vblankstart = var->yres; 1036 vblankstart = vdispend + 1;
906 vblankend = vtotal + 2; 1037 vblankend = vtotal;
1038
1039 if (info->var.vmode & FB_VMODE_INTERLACED) {
1040 vtotal /= 2;
1041 vdispend /= 2;
1042 vsyncstart /= 2;
1043 vsyncend /= 2;
1044 vblankstart /= 2;
1045 vblankend /= 2;
1046 }
907 1047
908 crtc_unlock(); 1048 enable_mmio(par);
909 write3CE(CyberControl, 8); 1049 crtc_unlock(par);
1050 write3CE(par, CyberControl, 8);
1051 tmp = 0xEB;
1052 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1053 tmp &= ~0x40;
1054 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1055 tmp &= ~0x80;
910 1056
911 if (flatpanel && var->xres < nativex) { 1057 if (par->flatpanel && var->xres < nativex) {
912 /* 1058 /*
913 * on flat panels with native size larger 1059 * on flat panels with native size larger
914 * than requested resolution decide whether 1060 * than requested resolution decide whether
915 * we stretch or center 1061 * we stretch or center
916 */ 1062 */
917 t_outb(0xEB, 0x3C2); 1063 t_outb(par, tmp | 0xC0, VGA_MIS_W);
918 1064
919 shadowmode_on(); 1065 shadowmode_on(par);
920 1066
921 if (center) 1067 if (center)
922 screen_center(); 1068 screen_center(par);
923 else if (stretch) 1069 else if (stretch)
924 screen_stretch(); 1070 screen_stretch(par);
925 1071
926 } else { 1072 } else {
927 t_outb(0x2B, 0x3C2); 1073 t_outb(par, tmp, VGA_MIS_W);
928 write3CE(CyberControl, 8); 1074 write3CE(par, CyberControl, 8);
929 } 1075 }
930 1076
931 /* vertical timing values */ 1077 /* vertical timing values */
932 write3X4(CRTVTotal, vtotal & 0xFF); 1078 write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);
933 write3X4(CRTVDispEnd, vdispend & 0xFF); 1079 write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);
934 write3X4(CRTVSyncStart, vsyncstart & 0xFF); 1080 write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);
935 write3X4(CRTVSyncEnd, (vsyncend & 0x0F)); 1081 write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));
936 write3X4(CRTVBlankStart, vblankstart & 0xFF); 1082 write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);
937 write3X4(CRTVBlankEnd, 0 /* p->vblankend & 0xFF */ ); 1083 write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);
938 1084
939 /* horizontal timing values */ 1085 /* horizontal timing values */
940 write3X4(CRTHTotal, htotal & 0xFF); 1086 write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);
941 write3X4(CRTHDispEnd, hdispend & 0xFF); 1087 write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);
942 write3X4(CRTHSyncStart, hsyncstart & 0xFF); 1088 write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);
943 write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2)); 1089 write3X4(par, VGA_CRTC_H_SYNC_END,
944 write3X4(CRTHBlankStart, hblankstart & 0xFF); 1090 (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
945 write3X4(CRTHBlankEnd, 0 /* (p->hblankend & 0x1F) */ ); 1091 write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);
1092 write3X4(par, VGA_CRTC_H_BLANK_END, hblankend & 0x1F);
946 1093
947 /* higher bits of vertical timing values */ 1094 /* higher bits of vertical timing values */
948 tmp = 0x10; 1095 tmp = 0x10;
@@ -954,39 +1101,43 @@ static int tridentfb_set_par(struct fb_info *info)
954 if (vtotal & 0x200) tmp |= 0x20; 1101 if (vtotal & 0x200) tmp |= 0x20;
955 if (vdispend & 0x200) tmp |= 0x40; 1102 if (vdispend & 0x200) tmp |= 0x40;
956 if (vsyncstart & 0x200) tmp |= 0x80; 1103 if (vsyncstart & 0x200) tmp |= 0x80;
957 write3X4(CRTOverflow, tmp); 1104 write3X4(par, VGA_CRTC_OVERFLOW, tmp);
958 1105
959 tmp = read3X4(CRTHiOrd) | 0x08; /* line compare bit 10 */ 1106 tmp = read3X4(par, CRTHiOrd) & 0x07;
1107 tmp |= 0x08; /* line compare bit 10 */
960 if (vtotal & 0x400) tmp |= 0x80; 1108 if (vtotal & 0x400) tmp |= 0x80;
961 if (vblankstart & 0x400) tmp |= 0x40; 1109 if (vblankstart & 0x400) tmp |= 0x40;
962 if (vsyncstart & 0x400) tmp |= 0x20; 1110 if (vsyncstart & 0x400) tmp |= 0x20;
963 if (vdispend & 0x400) tmp |= 0x10; 1111 if (vdispend & 0x400) tmp |= 0x10;
964 write3X4(CRTHiOrd, tmp); 1112 write3X4(par, CRTHiOrd, tmp);
965 1113
966 tmp = 0; 1114 tmp = (htotal >> 8) & 0x01;
967 if (htotal & 0x800) tmp |= 0x800 >> 11; 1115 tmp |= (hdispend >> 7) & 0x02;
968 if (hblankstart & 0x800) tmp |= 0x800 >> 7; 1116 tmp |= (hsyncstart >> 5) & 0x08;
969 write3X4(HorizOverflow, tmp); 1117 tmp |= (hblankstart >> 4) & 0x10;
1118 write3X4(par, HorizOverflow, tmp);
970 1119
971 tmp = 0x40; 1120 tmp = 0x40;
972 if (vblankstart & 0x200) tmp |= 0x20; 1121 if (vblankstart & 0x200) tmp |= 0x20;
973//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */ 1122//FIXME if (info->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; /* double scan for 200 line modes */
974 write3X4(CRTMaxScanLine, tmp); 1123 write3X4(par, VGA_CRTC_MAX_SCAN, tmp);
975 1124
976 write3X4(CRTLineCompare, 0xFF); 1125 write3X4(par, VGA_CRTC_LINE_COMPARE, 0xFF);
977 write3X4(CRTPRowScan, 0); 1126 write3X4(par, VGA_CRTC_PRESET_ROW, 0);
978 write3X4(CRTModeControl, 0xC3); 1127 write3X4(par, VGA_CRTC_MODE, 0xC3);
979 1128
980 write3X4(LinearAddReg, 0x20); /* enable linear addressing */ 1129 write3X4(par, LinearAddReg, 0x20); /* enable linear addressing */
981 1130
982 tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80; 1131 tmp = (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80;
983 write3X4(CRTCModuleTest, tmp); /* enable access extended memory */ 1132 /* enable access extended memory */
984 1133 write3X4(par, CRTCModuleTest, tmp);
985 write3X4(GraphEngReg, 0x80); /* enable GE for text acceleration */ 1134 tmp = read3CE(par, MiscIntContReg) & ~0x4;
1135 if (info->var.vmode & FB_VMODE_INTERLACED)
1136 tmp |= 0x4;
1137 write3CE(par, MiscIntContReg, tmp);
986 1138
987#ifdef CONFIG_FB_TRIDENT_ACCEL 1139 /* enable GE for text acceleration */
988 acc->init_accel(info->var.xres, bpp); 1140 write3X4(par, GraphEngReg, 0x80);
989#endif
990 1141
991 switch (bpp) { 1142 switch (bpp) {
992 case 8: 1143 case 8:
@@ -1003,57 +1154,59 @@ static int tridentfb_set_par(struct fb_info *info)
1003 break; 1154 break;
1004 } 1155 }
1005 1156
1006 write3X4(PixelBusReg, tmp); 1157 write3X4(par, PixelBusReg, tmp);
1007 1158
1008 tmp = 0x10; 1159 tmp = read3X4(par, DRAMControl);
1009 if (chipcyber) 1160 if (!is_oldprotect(par->chip_id))
1161 tmp |= 0x10;
1162 if (iscyber(par->chip_id))
1010 tmp |= 0x20; 1163 tmp |= 0x20;
1011 write3X4(DRAMControl, tmp); /* both IO, linear enable */ 1164 write3X4(par, DRAMControl, tmp); /* both IO, linear enable */
1012 1165
1013 write3X4(InterfaceSel, read3X4(InterfaceSel) | 0x40); 1166 write3X4(par, InterfaceSel, read3X4(par, InterfaceSel) | 0x40);
1014 write3X4(Performance, 0x92); 1167 if (!is_xp(par->chip_id))
1015 write3X4(PCIReg, 0x07); /* MMIO & PCI read and write burst enable */ 1168 write3X4(par, Performance, read3X4(par, Performance) | 0x10);
1169 /* MMIO & PCI read and write burst enable */
1170 if (par->chip_id != TGUI9440 && par->chip_id != IMAGE975)
1171 write3X4(par, PCIReg, read3X4(par, PCIReg) | 0x06);
1172
1173 vga_mm_wseq(par->io_virt, 0, 3);
1174 vga_mm_wseq(par->io_virt, 1, 1); /* set char clock 8 dots wide */
1175 /* enable 4 maps because needed in chain4 mode */
1176 vga_mm_wseq(par->io_virt, 2, 0x0F);
1177 vga_mm_wseq(par->io_virt, 3, 0);
1178 vga_mm_wseq(par->io_virt, 4, 0x0E); /* memory mode enable bitmaps ?? */
1016 1179
1017 /* convert from picoseconds to kHz */ 1180 /* convert from picoseconds to kHz */
1018 vclk = PICOS2KHZ(info->var.pixclock); 1181 vclk = PICOS2KHZ(info->var.pixclock);
1019 if (bpp == 32) 1182
1183 /* divide clock by 2 if 32bpp chain4 mode display and CPU path */
1184 tmp = read3CE(par, MiscExtFunc) & 0xF0;
1185 if (bpp == 32 || (par->chip_id == TGUI9440 && bpp == 16)) {
1186 tmp |= 8;
1020 vclk *= 2; 1187 vclk *= 2;
1021 set_vclk(vclk);
1022
1023 write3C4(0, 3);
1024 write3C4(1, 1); /* set char clock 8 dots wide */
1025 write3C4(2, 0x0F); /* enable 4 maps because needed in chain4 mode */
1026 write3C4(3, 0);
1027 write3C4(4, 0x0E); /* memory mode enable bitmaps ?? */
1028
1029 write3CE(MiscExtFunc, (bpp == 32) ? 0x1A : 0x12); /* divide clock by 2 if 32bpp */
1030 /* chain4 mode display and CPU path */
1031 write3CE(0x5, 0x40); /* no CGA compat, allow 256 col */
1032 write3CE(0x6, 0x05); /* graphics mode */
1033 write3CE(0x7, 0x0F); /* planes? */
1034
1035 if (chip_id == CYBERBLADEXPAi1) {
1036 /* This fixes snow-effect in 32 bpp */
1037 write3X4(CRTHSyncStart, 0x84);
1038 } 1188 }
1189 set_vclk(par, vclk);
1190 write3CE(par, MiscExtFunc, tmp | 0x12);
1191 write3CE(par, 0x5, 0x40); /* no CGA compat, allow 256 col */
1192 write3CE(par, 0x6, 0x05); /* graphics mode */
1193 write3CE(par, 0x7, 0x0F); /* planes? */
1039 1194
1040 writeAttr(0x10, 0x41); /* graphics mode and support 256 color modes */ 1195 /* graphics mode and support 256 color modes */
1041 writeAttr(0x12, 0x0F); /* planes */ 1196 writeAttr(par, 0x10, 0x41);
1042 writeAttr(0x13, 0); /* horizontal pel panning */ 1197 writeAttr(par, 0x12, 0x0F); /* planes */
1198 writeAttr(par, 0x13, 0); /* horizontal pel panning */
1043 1199
1044 /* colors */ 1200 /* colors */
1045 for (tmp = 0; tmp < 0x10; tmp++) 1201 for (tmp = 0; tmp < 0x10; tmp++)
1046 writeAttr(tmp, tmp); 1202 writeAttr(par, tmp, tmp);
1047 readb(par->io_virt + CRT + 0x0A); /* flip-flop to index */ 1203 fb_readb(par->io_virt + VGA_IS1_RC); /* flip-flop to index */
1048 t_outb(0x20, 0x3C0); /* enable attr */ 1204 t_outb(par, 0x20, VGA_ATT_W); /* enable attr */
1049 1205
1050 switch (bpp) { 1206 switch (bpp) {
1051 case 8: 1207 case 8:
1052 tmp = 0; 1208 tmp = 0;
1053 break; 1209 break;
1054 case 15:
1055 tmp = 0x10;
1056 break;
1057 case 16: 1210 case 16:
1058 tmp = 0x30; 1211 tmp = 0x30;
1059 break; 1212 break;
@@ -1063,19 +1216,23 @@ static int tridentfb_set_par(struct fb_info *info)
1063 break; 1216 break;
1064 } 1217 }
1065 1218
1066 t_inb(0x3C8); 1219 t_inb(par, VGA_PEL_IW);
1067 t_inb(0x3C6); 1220 t_inb(par, VGA_PEL_MSK);
1068 t_inb(0x3C6); 1221 t_inb(par, VGA_PEL_MSK);
1069 t_inb(0x3C6); 1222 t_inb(par, VGA_PEL_MSK);
1070 t_inb(0x3C6); 1223 t_inb(par, VGA_PEL_MSK);
1071 t_outb(tmp, 0x3C6); 1224 t_outb(par, tmp, VGA_PEL_MSK);
1072 t_inb(0x3C8); 1225 t_inb(par, VGA_PEL_IW);
1073 1226
1074 if (flatpanel) 1227 if (par->flatpanel)
1075 set_number_of_lines(info->var.yres); 1228 set_number_of_lines(par, info->var.yres);
1076 set_lwidth(info->var.xres * bpp / (4 * 16)); 1229 info->fix.line_length = info->var.xres_virtual * bpp / 8;
1230 set_lwidth(par, info->fix.line_length / 8);
1231
1232 if (!(info->flags & FBINFO_HWACCEL_DISABLED))
1233 par->init_accel(par, info->var.xres_virtual, bpp);
1234
1077 info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 1235 info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1078 info->fix.line_length = info->var.xres * (bpp >> 3);
1079 info->cmap.len = (bpp == 8) ? 256 : 16; 1236 info->cmap.len = (bpp == 8) ? 256 : 16;
1080 debug("exit\n"); 1237 debug("exit\n");
1081 return 0; 1238 return 0;
@@ -1087,17 +1244,18 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1087 struct fb_info *info) 1244 struct fb_info *info)
1088{ 1245{
1089 int bpp = info->var.bits_per_pixel; 1246 int bpp = info->var.bits_per_pixel;
1247 struct tridentfb_par *par = info->par;
1090 1248
1091 if (regno >= info->cmap.len) 1249 if (regno >= info->cmap.len)
1092 return 1; 1250 return 1;
1093 1251
1094 if (bpp == 8) { 1252 if (bpp == 8) {
1095 t_outb(0xFF, 0x3C6); 1253 t_outb(par, 0xFF, VGA_PEL_MSK);
1096 t_outb(regno, 0x3C8); 1254 t_outb(par, regno, VGA_PEL_IW);
1097 1255
1098 t_outb(red >> 10, 0x3C9); 1256 t_outb(par, red >> 10, VGA_PEL_D);
1099 t_outb(green >> 10, 0x3C9); 1257 t_outb(par, green >> 10, VGA_PEL_D);
1100 t_outb(blue >> 10, 0x3C9); 1258 t_outb(par, blue >> 10, VGA_PEL_D);
1101 1259
1102 } else if (regno < 16) { 1260 } else if (regno < 16) {
1103 if (bpp == 16) { /* RGB 565 */ 1261 if (bpp == 16) { /* RGB 565 */
@@ -1108,28 +1266,28 @@ static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1108 col |= col << 16; 1266 col |= col << 16;
1109 ((u32 *)(info->pseudo_palette))[regno] = col; 1267 ((u32 *)(info->pseudo_palette))[regno] = col;
1110 } else if (bpp == 32) /* ARGB 8888 */ 1268 } else if (bpp == 32) /* ARGB 8888 */
1111 ((u32*)info->pseudo_palette)[regno] = 1269 ((u32 *)info->pseudo_palette)[regno] =
1112 ((transp & 0xFF00) << 16) | 1270 ((transp & 0xFF00) << 16) |
1113 ((red & 0xFF00) << 8) | 1271 ((red & 0xFF00) << 8) |
1114 ((green & 0xFF00)) | 1272 ((green & 0xFF00)) |
1115 ((blue & 0xFF00) >> 8); 1273 ((blue & 0xFF00) >> 8);
1116 } 1274 }
1117 1275
1118/* debug("exit\n"); */
1119 return 0; 1276 return 0;
1120} 1277}
1121 1278
1122/* Try blanking the screen.For flat panels it does nothing */ 1279/* Try blanking the screen. For flat panels it does nothing */
1123static int tridentfb_blank(int blank_mode, struct fb_info *info) 1280static int tridentfb_blank(int blank_mode, struct fb_info *info)
1124{ 1281{
1125 unsigned char PMCont, DPMSCont; 1282 unsigned char PMCont, DPMSCont;
1283 struct tridentfb_par *par = info->par;
1126 1284
1127 debug("enter\n"); 1285 debug("enter\n");
1128 if (flatpanel) 1286 if (par->flatpanel)
1129 return 0; 1287 return 0;
1130 t_outb(0x04, 0x83C8); /* Read DPMS Control */ 1288 t_outb(par, 0x04, 0x83C8); /* Read DPMS Control */
1131 PMCont = t_inb(0x83C6) & 0xFC; 1289 PMCont = t_inb(par, 0x83C6) & 0xFC;
1132 DPMSCont = read3CE(PowerStatus) & 0xFC; 1290 DPMSCont = read3CE(par, PowerStatus) & 0xFC;
1133 switch (blank_mode) { 1291 switch (blank_mode) {
1134 case FB_BLANK_UNBLANK: 1292 case FB_BLANK_UNBLANK:
1135 /* Screen: On, HSync: On, VSync: On */ 1293 /* Screen: On, HSync: On, VSync: On */
@@ -1155,9 +1313,9 @@ static int tridentfb_blank(int blank_mode, struct fb_info *info)
1155 break; 1313 break;
1156 } 1314 }
1157 1315
1158 write3CE(PowerStatus, DPMSCont); 1316 write3CE(par, PowerStatus, DPMSCont);
1159 t_outb(4, 0x83C8); 1317 t_outb(par, 4, 0x83C8);
1160 t_outb(PMCont, 0x83C6); 1318 t_outb(par, PMCont, 0x83C6);
1161 1319
1162 debug("exit\n"); 1320 debug("exit\n");
1163 1321
@@ -1174,33 +1332,46 @@ static struct fb_ops tridentfb_ops = {
1174 .fb_set_par = tridentfb_set_par, 1332 .fb_set_par = tridentfb_set_par,
1175 .fb_fillrect = tridentfb_fillrect, 1333 .fb_fillrect = tridentfb_fillrect,
1176 .fb_copyarea = tridentfb_copyarea, 1334 .fb_copyarea = tridentfb_copyarea,
1177 .fb_imageblit = cfb_imageblit, 1335 .fb_imageblit = tridentfb_imageblit,
1336#ifdef CONFIG_FB_TRIDENT_ACCEL
1337 .fb_sync = tridentfb_sync,
1338#endif
1178}; 1339};
1179 1340
1180static int __devinit trident_pci_probe(struct pci_dev * dev, 1341static int __devinit trident_pci_probe(struct pci_dev *dev,
1181 const struct pci_device_id * id) 1342 const struct pci_device_id *id)
1182{ 1343{
1183 int err; 1344 int err;
1184 unsigned char revision; 1345 unsigned char revision;
1346 struct fb_info *info;
1347 struct tridentfb_par *default_par;
1348 int chip3D;
1349 int chip_id;
1185 1350
1186 err = pci_enable_device(dev); 1351 err = pci_enable_device(dev);
1187 if (err) 1352 if (err)
1188 return err; 1353 return err;
1189 1354
1190 chip_id = id->device; 1355 info = framebuffer_alloc(sizeof(struct tridentfb_par), &dev->dev);
1356 if (!info)
1357 return -ENOMEM;
1358 default_par = info->par;
1191 1359
1192 if (chip_id == CYBERBLADEi1) 1360 chip_id = id->device;
1193 output("*** Please do use cyblafb, Cyberblade/i1 support "
1194 "will soon be removed from tridentfb!\n");
1195 1361
1362#ifndef CONFIG_FB_TRIDENT_ACCEL
1363 noaccel = 1;
1364#endif
1196 1365
1197 /* If PCI id is 0x9660 then further detect chip type */ 1366 /* If PCI id is 0x9660 then further detect chip type */
1198 1367
1199 if (chip_id == TGUI9660) { 1368 if (chip_id == TGUI9660) {
1200 outb(RevisionID, 0x3C4); 1369 revision = vga_io_rseq(RevisionID);
1201 revision = inb(0x3C5);
1202 1370
1203 switch (revision) { 1371 switch (revision) {
1372 case 0x21:
1373 chip_id = PROVIDIA9685;
1374 break;
1204 case 0x22: 1375 case 0x22:
1205 case 0x23: 1376 case 0x23:
1206 chip_id = CYBER9397; 1377 chip_id = CYBER9397;
@@ -1229,123 +1400,170 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
1229 } 1400 }
1230 1401
1231 chip3D = is3Dchip(chip_id); 1402 chip3D = is3Dchip(chip_id);
1232 chipcyber = iscyber(chip_id);
1233 1403
1234 if (is_xp(chip_id)) { 1404 if (is_xp(chip_id)) {
1235 acc = &accel_xp; 1405 default_par->init_accel = xp_init_accel;
1406 default_par->wait_engine = xp_wait_engine;
1407 default_par->fill_rect = xp_fill_rect;
1408 default_par->copy_rect = xp_copy_rect;
1409 tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADEXP;
1236 } else if (is_blade(chip_id)) { 1410 } else if (is_blade(chip_id)) {
1237 acc = &accel_blade; 1411 default_par->init_accel = blade_init_accel;
1238 } else { 1412 default_par->wait_engine = blade_wait_engine;
1239 acc = &accel_image; 1413 default_par->fill_rect = blade_fill_rect;
1414 default_par->copy_rect = blade_copy_rect;
1415 default_par->image_blit = blade_image_blit;
1416 tridentfb_fix.accel = FB_ACCEL_TRIDENT_BLADE3D;
1417 } else if (chip3D) { /* 3DImage family left */
1418 default_par->init_accel = image_init_accel;
1419 default_par->wait_engine = image_wait_engine;
1420 default_par->fill_rect = image_fill_rect;
1421 default_par->copy_rect = image_copy_rect;
1422 tridentfb_fix.accel = FB_ACCEL_TRIDENT_3DIMAGE;
1423 } else { /* TGUI 9440/96XX family */
1424 default_par->init_accel = tgui_init_accel;
1425 default_par->wait_engine = xp_wait_engine;
1426 default_par->fill_rect = tgui_fill_rect;
1427 default_par->copy_rect = tgui_copy_rect;
1428 tridentfb_fix.accel = FB_ACCEL_TRIDENT_TGUI;
1240 } 1429 }
1241 1430
1242 /* acceleration is on by default for 3D chips */ 1431 default_par->chip_id = chip_id;
1243 defaultaccel = chip3D && !noaccel;
1244
1245 fb_info.par = &default_par;
1246 1432
1247 /* setup MMIO region */ 1433 /* setup MMIO region */
1248 tridentfb_fix.mmio_start = pci_resource_start(dev, 1); 1434 tridentfb_fix.mmio_start = pci_resource_start(dev, 1);
1249 tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000; 1435 tridentfb_fix.mmio_len = pci_resource_len(dev, 1);
1250 1436
1251 if (!request_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len, "tridentfb")) { 1437 if (!request_mem_region(tridentfb_fix.mmio_start,
1438 tridentfb_fix.mmio_len, "tridentfb")) {
1252 debug("request_region failed!\n"); 1439 debug("request_region failed!\n");
1440 framebuffer_release(info);
1253 return -1; 1441 return -1;
1254 } 1442 }
1255 1443
1256 default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); 1444 default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start,
1445 tridentfb_fix.mmio_len);
1257 1446
1258 if (!default_par.io_virt) { 1447 if (!default_par->io_virt) {
1259 debug("ioremap failed\n"); 1448 debug("ioremap failed\n");
1260 err = -1; 1449 err = -1;
1261 goto out_unmap1; 1450 goto out_unmap1;
1262 } 1451 }
1263 1452
1264 enable_mmio(); 1453 enable_mmio(default_par);
1265 1454
1266 /* setup framebuffer memory */ 1455 /* setup framebuffer memory */
1267 tridentfb_fix.smem_start = pci_resource_start(dev, 0); 1456 tridentfb_fix.smem_start = pci_resource_start(dev, 0);
1268 tridentfb_fix.smem_len = get_memsize(); 1457 tridentfb_fix.smem_len = get_memsize(default_par);
1269 1458
1270 if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { 1459 if (!request_mem_region(tridentfb_fix.smem_start,
1460 tridentfb_fix.smem_len, "tridentfb")) {
1271 debug("request_mem_region failed!\n"); 1461 debug("request_mem_region failed!\n");
1272 disable_mmio(); 1462 disable_mmio(info->par);
1273 err = -1; 1463 err = -1;
1274 goto out_unmap1; 1464 goto out_unmap1;
1275 } 1465 }
1276 1466
1277 fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start, 1467 info->screen_base = ioremap_nocache(tridentfb_fix.smem_start,
1278 tridentfb_fix.smem_len); 1468 tridentfb_fix.smem_len);
1279 1469
1280 if (!fb_info.screen_base) { 1470 if (!info->screen_base) {
1281 debug("ioremap failed\n"); 1471 debug("ioremap failed\n");
1282 err = -1; 1472 err = -1;
1283 goto out_unmap2; 1473 goto out_unmap2;
1284 } 1474 }
1285 1475
1286 output("%s board found\n", pci_name(dev)); 1476 default_par->flatpanel = is_flatpanel(default_par);
1287 displaytype = get_displaytype();
1288 1477
1289 if (flatpanel) 1478 if (default_par->flatpanel)
1290 nativex = get_nativex(); 1479 nativex = get_nativex(default_par);
1291 1480
1292 fb_info.fix = tridentfb_fix; 1481 info->fix = tridentfb_fix;
1293 fb_info.fbops = &tridentfb_ops; 1482 info->fbops = &tridentfb_ops;
1483 info->pseudo_palette = default_par->pseudo_pal;
1294 1484
1485 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1486 if (!noaccel && default_par->init_accel) {
1487 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1488 info->flags |= FBINFO_HWACCEL_COPYAREA;
1489 info->flags |= FBINFO_HWACCEL_FILLRECT;
1490 } else
1491 info->flags |= FBINFO_HWACCEL_DISABLED;
1295 1492
1296 fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1493 info->pixmap.addr = kmalloc(4096, GFP_KERNEL);
1297#ifdef CONFIG_FB_TRIDENT_ACCEL 1494 if (!info->pixmap.addr) {
1298 fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; 1495 err = -ENOMEM;
1299#endif 1496 goto out_unmap2;
1300 fb_info.pseudo_palette = pseudo_pal; 1497 }
1498
1499 info->pixmap.size = 4096;
1500 info->pixmap.buf_align = 4;
1501 info->pixmap.scan_align = 1;
1502 info->pixmap.access_align = 32;
1503 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1301 1504
1302 if (!fb_find_mode(&default_var, &fb_info, 1505 if (default_par->image_blit) {
1506 info->flags |= FBINFO_HWACCEL_IMAGEBLIT;
1507 info->pixmap.scan_align = 4;
1508 }
1509
1510 if (noaccel) {
1511 printk(KERN_DEBUG "disabling acceleration\n");
1512 info->flags |= FBINFO_HWACCEL_DISABLED;
1513 info->pixmap.scan_align = 1;
1514 }
1515
1516 if (!fb_find_mode(&info->var, info,
1303 mode_option, NULL, 0, NULL, bpp)) { 1517 mode_option, NULL, 0, NULL, bpp)) {
1304 err = -EINVAL; 1518 err = -EINVAL;
1305 goto out_unmap2; 1519 goto out_unmap2;
1306 } 1520 }
1307 err = fb_alloc_cmap(&fb_info.cmap, 256, 0); 1521 err = fb_alloc_cmap(&info->cmap, 256, 0);
1308 if (err < 0) 1522 if (err < 0)
1309 goto out_unmap2; 1523 goto out_unmap2;
1310 1524
1311 if (defaultaccel && acc) 1525 info->var.activate |= FB_ACTIVATE_NOW;
1312 default_var.accel_flags |= FB_ACCELF_TEXT; 1526 info->device = &dev->dev;
1313 else 1527 if (register_framebuffer(info) < 0) {
1314 default_var.accel_flags &= ~FB_ACCELF_TEXT; 1528 printk(KERN_ERR "tridentfb: could not register framebuffer\n");
1315 default_var.activate |= FB_ACTIVATE_NOW; 1529 fb_dealloc_cmap(&info->cmap);
1316 fb_info.var = default_var;
1317 fb_info.device = &dev->dev;
1318 if (register_framebuffer(&fb_info) < 0) {
1319 printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
1320 fb_dealloc_cmap(&fb_info.cmap);
1321 err = -EINVAL; 1530 err = -EINVAL;
1322 goto out_unmap2; 1531 goto out_unmap2;
1323 } 1532 }
1324 output("fb%d: %s frame buffer device %dx%d-%dbpp\n", 1533 output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
1325 fb_info.node, fb_info.fix.id, default_var.xres, 1534 info->node, info->fix.id, info->var.xres,
1326 default_var.yres, default_var.bits_per_pixel); 1535 info->var.yres, info->var.bits_per_pixel);
1536
1537 pci_set_drvdata(dev, info);
1327 return 0; 1538 return 0;
1328 1539
1329out_unmap2: 1540out_unmap2:
1330 if (fb_info.screen_base) 1541 kfree(info->pixmap.addr);
1331 iounmap(fb_info.screen_base); 1542 if (info->screen_base)
1543 iounmap(info->screen_base);
1332 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); 1544 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
1333 disable_mmio(); 1545 disable_mmio(info->par);
1334out_unmap1: 1546out_unmap1:
1335 if (default_par.io_virt) 1547 if (default_par->io_virt)
1336 iounmap(default_par.io_virt); 1548 iounmap(default_par->io_virt);
1337 release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); 1549 release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
1550 framebuffer_release(info);
1338 return err; 1551 return err;
1339} 1552}
1340 1553
1341static void __devexit trident_pci_remove(struct pci_dev *dev) 1554static void __devexit trident_pci_remove(struct pci_dev *dev)
1342{ 1555{
1343 struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par; 1556 struct fb_info *info = pci_get_drvdata(dev);
1344 unregister_framebuffer(&fb_info); 1557 struct tridentfb_par *par = info->par;
1558
1559 unregister_framebuffer(info);
1345 iounmap(par->io_virt); 1560 iounmap(par->io_virt);
1346 iounmap(fb_info.screen_base); 1561 iounmap(info->screen_base);
1347 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); 1562 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
1348 release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); 1563 release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
1564 pci_set_drvdata(dev, NULL);
1565 kfree(info->pixmap.addr);
1566 framebuffer_release(info);
1349} 1567}
1350 1568
1351/* List of boards that we are trying to support */ 1569/* List of boards that we are trying to support */
@@ -1358,6 +1576,7 @@ static struct pci_device_id trident_devices[] = {
1358 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1576 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1359 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1577 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEAi1D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1360 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1578 {PCI_VENDOR_ID_TRIDENT, CYBERBLADEE4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1579 {PCI_VENDOR_ID_TRIDENT, TGUI9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1361 {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1580 {PCI_VENDOR_ID_TRIDENT, TGUI9660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1362 {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1581 {PCI_VENDOR_ID_TRIDENT, IMAGE975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1363 {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1582 {PCI_VENDOR_ID_TRIDENT, IMAGE985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -1399,9 +1618,9 @@ static int __init tridentfb_setup(char *options)
1399 if (!strncmp(opt, "noaccel", 7)) 1618 if (!strncmp(opt, "noaccel", 7))
1400 noaccel = 1; 1619 noaccel = 1;
1401 else if (!strncmp(opt, "fp", 2)) 1620 else if (!strncmp(opt, "fp", 2))
1402 displaytype = DISPLAY_FP; 1621 fp = 1;
1403 else if (!strncmp(opt, "crt", 3)) 1622 else if (!strncmp(opt, "crt", 3))
1404 displaytype = DISPLAY_CRT; 1623 fp = 0;
1405 else if (!strncmp(opt, "bpp=", 4)) 1624 else if (!strncmp(opt, "bpp=", 4))
1406 bpp = simple_strtoul(opt + 4, NULL, 0); 1625 bpp = simple_strtoul(opt + 4, NULL, 0);
1407 else if (!strncmp(opt, "center", 6)) 1626 else if (!strncmp(opt, "center", 6))
@@ -1430,7 +1649,6 @@ static int __init tridentfb_init(void)
1430 return -ENODEV; 1649 return -ENODEV;
1431 tridentfb_setup(option); 1650 tridentfb_setup(option);
1432#endif 1651#endif
1433 output("Trident framebuffer %s initializing\n", VERSION);
1434 return pci_register_driver(&tridentfb_pci_driver); 1652 return pci_register_driver(&tridentfb_pci_driver);
1435} 1653}
1436 1654
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index cdbb56edb6cb..6c2d37fdd3b9 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -516,10 +516,12 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
516 516
517 err = uvesafb_exec(task); 517 err = uvesafb_exec(task);
518 if (err || (task->t.regs.eax & 0xffff) != 0x004f) { 518 if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
519 printk(KERN_ERR "uvesafb: Getting mode info block " 519 printk(KERN_WARNING "uvesafb: Getting mode info block "
520 "for mode 0x%x failed (eax=0x%x, err=%d)\n", 520 "for mode 0x%x failed (eax=0x%x, err=%d)\n",
521 *mode, (u32)task->t.regs.eax, err); 521 *mode, (u32)task->t.regs.eax, err);
522 return -EINVAL; 522 mode++;
523 par->vbe_modes_cnt--;
524 continue;
523 } 525 }
524 526
525 mib = task->buf; 527 mib = task->buf;
@@ -548,7 +550,10 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
548 mib->depth = mib->bits_per_pixel; 550 mib->depth = mib->bits_per_pixel;
549 } 551 }
550 552
551 return 0; 553 if (par->vbe_modes_cnt > 0)
554 return 0;
555 else
556 return -EINVAL;
552} 557}
553 558
554/* 559/*
@@ -2054,8 +2059,8 @@ MODULE_PARM_DESC(maxhf,
2054module_param(maxvf, ushort, 0); 2059module_param(maxvf, ushort, 0);
2055MODULE_PARM_DESC(maxvf, 2060MODULE_PARM_DESC(maxvf,
2056 "Maximum vertical frequency [Hz], overrides EDID data"); 2061 "Maximum vertical frequency [Hz], overrides EDID data");
2057module_param_named(mode, mode_option, charp, 0); 2062module_param(mode_option, charp, 0);
2058MODULE_PARM_DESC(mode, 2063MODULE_PARM_DESC(mode_option,
2059 "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\""); 2064 "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
2060module_param(vbemode, ushort, 0); 2065module_param(vbemode, ushort, 0);
2061MODULE_PARM_DESC(vbemode, 2066MODULE_PARM_DESC(vbemode,
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
index c4aba59d4809..7491abfcf1fc 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/vermilion/vermilion.h
@@ -30,7 +30,6 @@
30#define _VERMILION_H_ 30#define _VERMILION_H_
31 31
32#include <linux/kernel.h> 32#include <linux/kernel.h>
33#include <linux/version.h>
34#include <linux/pci.h> 33#include <linux/pci.h>
35#include <asm/atomic.h> 34#include <asm/atomic.h>
36#include <linux/mutex.h> 35#include <linux/mutex.h>
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 072638a9528a..93fe08d6c78f 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -443,19 +443,29 @@ static int vfb_mmap(struct fb_info *info,
443} 443}
444 444
445#ifndef MODULE 445#ifndef MODULE
446/*
447 * The virtual framebuffer driver is only enabled if explicitly
448 * requested by passing 'video=vfb:' (or any actual options).
449 */
446static int __init vfb_setup(char *options) 450static int __init vfb_setup(char *options)
447{ 451{
448 char *this_opt; 452 char *this_opt;
449 453
454 vfb_enable = 0;
455
456 if (!options)
457 return 1;
458
450 vfb_enable = 1; 459 vfb_enable = 1;
451 460
452 if (!options || !*options) 461 if (!*options)
453 return 1; 462 return 1;
454 463
455 while ((this_opt = strsep(&options, ",")) != NULL) { 464 while ((this_opt = strsep(&options, ",")) != NULL) {
456 if (!*this_opt) 465 if (!*this_opt)
457 continue; 466 continue;
458 if (!strncmp(this_opt, "disable", 7)) 467 /* Test disable for backwards compatibility */
468 if (!strcmp(this_opt, "disable"))
459 vfb_enable = 0; 469 vfb_enable = 0;
460 } 470 }
461 return 1; 471 return 1;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 9b3c5923365e..5b2938903ac2 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -26,18 +26,6 @@
26#include <asm/io.h> 26#include <asm/io.h>
27#include <video/vga.h> 27#include <video/vga.h>
28 28
29#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */
30#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */
31
32#define SET_RESET_INDEX VGA_GFX_SR_VALUE /* Set/Reset Register index. */
33#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE /* Enable Set/Reset Register index. */
34#define DATA_ROTATE_INDEX VGA_GFX_DATA_ROTATE /* Data Rotate Register index. */
35#define GRAPHICS_MODE_INDEX VGA_GFX_MODE /* Graphics Mode Register index. */
36#define BIT_MASK_INDEX VGA_GFX_BIT_MASK /* Bit Mask Register index. */
37
38#define dac_reg (VGA_PEL_IW)
39#define dac_val (VGA_PEL_D)
40
41#define VGA_FB_PHYS 0xA0000 29#define VGA_FB_PHYS 0xA0000
42#define VGA_FB_PHYS_LEN 65536 30#define VGA_FB_PHYS_LEN 65536
43 31
@@ -70,7 +58,6 @@ struct vga16fb_par {
70 unsigned char ClockingMode; /* Seq-Controller:01h */ 58 unsigned char ClockingMode; /* Seq-Controller:01h */
71 } vga_state; 59 } vga_state;
72 struct vgastate state; 60 struct vgastate state;
73 struct mutex open_lock;
74 unsigned int ref_count; 61 unsigned int ref_count;
75 int palette_blanked, vesa_blanked, mode, isVGA; 62 int palette_blanked, vesa_blanked, mode, isVGA;
76 u8 misc, pel_msk, vss, clkdiv; 63 u8 misc, pel_msk, vss, clkdiv;
@@ -108,7 +95,7 @@ static struct fb_fix_screeninfo vga16fb_fix __initdata = {
108 .visual = FB_VISUAL_PSEUDOCOLOR, 95 .visual = FB_VISUAL_PSEUDOCOLOR,
109 .xpanstep = 8, 96 .xpanstep = 8,
110 .ypanstep = 1, 97 .ypanstep = 1,
111 .line_length = 640/8, 98 .line_length = 640 / 8,
112 .accel = FB_ACCEL_NONE 99 .accel = FB_ACCEL_NONE
113}; 100};
114 101
@@ -135,23 +122,22 @@ static inline int setmode(int mode)
135{ 122{
136 int oldmode; 123 int oldmode;
137 124
138 vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX); 125 oldmode = vga_io_rgfx(VGA_GFX_MODE);
139 oldmode = vga_io_r(GRAPHICS_DATA_REG); 126 vga_io_w(VGA_GFX_D, mode);
140 vga_io_w(GRAPHICS_DATA_REG, mode);
141 return oldmode; 127 return oldmode;
142} 128}
143 129
144/* Select the Bit Mask Register and return its value. */ 130/* Select the Bit Mask Register and return its value. */
145static inline int selectmask(void) 131static inline int selectmask(void)
146{ 132{
147 return vga_io_rgfx(BIT_MASK_INDEX); 133 return vga_io_rgfx(VGA_GFX_BIT_MASK);
148} 134}
149 135
150/* Set the value of the Bit Mask Register. It must already have been 136/* Set the value of the Bit Mask Register. It must already have been
151 selected with selectmask(). */ 137 selected with selectmask(). */
152static inline void setmask(int mask) 138static inline void setmask(int mask)
153{ 139{
154 vga_io_w(GRAPHICS_DATA_REG, mask); 140 vga_io_w(VGA_GFX_D, mask);
155} 141}
156 142
157/* Set the Data Rotate Register and return its old value. 143/* Set the Data Rotate Register and return its old value.
@@ -161,9 +147,8 @@ static inline int setop(int op)
161{ 147{
162 int oldop; 148 int oldop;
163 149
164 vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX); 150 oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
165 oldop = vga_io_r(GRAPHICS_DATA_REG); 151 vga_io_w(VGA_GFX_D, op);
166 vga_io_w(GRAPHICS_DATA_REG, op);
167 return oldop; 152 return oldop;
168} 153}
169 154
@@ -173,9 +158,8 @@ static inline int setsr(int sr)
173{ 158{
174 int oldsr; 159 int oldsr;
175 160
176 vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX); 161 oldsr = vga_io_rgfx(VGA_GFX_SR_ENABLE);
177 oldsr = vga_io_r(GRAPHICS_DATA_REG); 162 vga_io_w(VGA_GFX_D, sr);
178 vga_io_w(GRAPHICS_DATA_REG, sr);
179 return oldsr; 163 return oldsr;
180} 164}
181 165
@@ -184,22 +168,21 @@ static inline int setcolor(int color)
184{ 168{
185 int oldcolor; 169 int oldcolor;
186 170
187 vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX); 171 oldcolor = vga_io_rgfx(VGA_GFX_SR_VALUE);
188 oldcolor = vga_io_r(GRAPHICS_DATA_REG); 172 vga_io_w(VGA_GFX_D, color);
189 vga_io_w(GRAPHICS_DATA_REG, color);
190 return oldcolor; 173 return oldcolor;
191} 174}
192 175
193/* Return the value in the Graphics Address Register. */ 176/* Return the value in the Graphics Address Register. */
194static inline int getindex(void) 177static inline int getindex(void)
195{ 178{
196 return vga_io_r(GRAPHICS_ADDR_REG); 179 return vga_io_r(VGA_GFX_I);
197} 180}
198 181
199/* Set the value in the Graphics Address Register. */ 182/* Set the value in the Graphics Address Register. */
200static inline void setindex(int index) 183static inline void setindex(int index)
201{ 184{
202 vga_io_w(GRAPHICS_ADDR_REG, index); 185 vga_io_w(VGA_GFX_I, index);
203} 186}
204 187
205static void vga16fb_pan_var(struct fb_info *info, 188static void vga16fb_pan_var(struct fb_info *info,
@@ -302,7 +285,6 @@ static int vga16fb_open(struct fb_info *info, int user)
302{ 285{
303 struct vga16fb_par *par = info->par; 286 struct vga16fb_par *par = info->par;
304 287
305 mutex_lock(&par->open_lock);
306 if (!par->ref_count) { 288 if (!par->ref_count) {
307 memset(&par->state, 0, sizeof(struct vgastate)); 289 memset(&par->state, 0, sizeof(struct vgastate));
308 par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | 290 par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
@@ -310,7 +292,6 @@ static int vga16fb_open(struct fb_info *info, int user)
310 save_vga(&par->state); 292 save_vga(&par->state);
311 } 293 }
312 par->ref_count++; 294 par->ref_count++;
313 mutex_unlock(&par->open_lock);
314 295
315 return 0; 296 return 0;
316} 297}
@@ -319,15 +300,12 @@ static int vga16fb_release(struct fb_info *info, int user)
319{ 300{
320 struct vga16fb_par *par = info->par; 301 struct vga16fb_par *par = info->par;
321 302
322 mutex_lock(&par->open_lock); 303 if (!par->ref_count)
323 if (!par->ref_count) {
324 mutex_unlock(&par->open_lock);
325 return -EINVAL; 304 return -EINVAL;
326 } 305
327 if (par->ref_count == 1) 306 if (par->ref_count == 1)
328 restore_vga(&par->state); 307 restore_vga(&par->state);
329 par->ref_count--; 308 par->ref_count--;
330 mutex_unlock(&par->open_lock);
331 309
332 return 0; 310 return 0;
333} 311}
@@ -672,10 +650,10 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b
672 650
673static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) 651static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
674{ 652{
675 outb(regno, dac_reg); 653 outb(regno, VGA_PEL_IW);
676 outb(red >> 10, dac_val); 654 outb(red >> 10, VGA_PEL_D);
677 outb(green >> 10, dac_val); 655 outb(green >> 10, VGA_PEL_D);
678 outb(blue >> 10, dac_val); 656 outb(blue >> 10, VGA_PEL_D);
679} 657}
680 658
681static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, 659static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -719,28 +697,15 @@ static int vga16fb_pan_display(struct fb_var_screeninfo *var,
719 blanking code was originally by Huang shi chao, and modified by 697 blanking code was originally by Huang shi chao, and modified by
720 Christoph Rimek (chrimek@toppoint.de) and todd j. derr 698 Christoph Rimek (chrimek@toppoint.de) and todd j. derr
721 (tjd@barefoot.org) for Linux. */ 699 (tjd@barefoot.org) for Linux. */
722#define attrib_port VGA_ATC_IW
723#define seq_port_reg VGA_SEQ_I
724#define seq_port_val VGA_SEQ_D
725#define gr_port_reg VGA_GFX_I
726#define gr_port_val VGA_GFX_D
727#define video_misc_rd VGA_MIS_R
728#define video_misc_wr VGA_MIS_W
729#define vga_video_port_reg VGA_CRT_IC
730#define vga_video_port_val VGA_CRT_DC
731 700
732static void vga_vesa_blank(struct vga16fb_par *par, int mode) 701static void vga_vesa_blank(struct vga16fb_par *par, int mode)
733{ 702{
734 unsigned char SeqCtrlIndex; 703 unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
735 unsigned char CrtCtrlIndex; 704 unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
736 705
737 //cli();
738 SeqCtrlIndex = vga_io_r(seq_port_reg);
739 CrtCtrlIndex = vga_io_r(vga_video_port_reg);
740
741 /* save original values of VGA controller registers */ 706 /* save original values of VGA controller registers */
742 if(!par->vesa_blanked) { 707 if(!par->vesa_blanked) {
743 par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd); 708 par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
744 //sti(); 709 //sti();
745 710
746 par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ 711 par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */
@@ -756,12 +721,11 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
756 721
757 /* assure that video is enabled */ 722 /* assure that video is enabled */
758 /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ 723 /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
759 //cli();
760 vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); 724 vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
761 725
762 /* test for vertical retrace in process.... */ 726 /* test for vertical retrace in process.... */
763 if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) 727 if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
764 vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef); 728 vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO & 0xef);
765 729
766 /* 730 /*
767 * Set <End of vertical retrace> to minimum (0) and 731 * Set <End of vertical retrace> to minimum (0) and
@@ -769,12 +733,10 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
769 * Result: turn off vertical sync (VSync) pulse. 733 * Result: turn off vertical sync (VSync) pulse.
770 */ 734 */
771 if (mode & FB_BLANK_VSYNC_SUSPEND) { 735 if (mode & FB_BLANK_VSYNC_SUSPEND) {
772 outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ 736 vga_io_wcrt(VGA_CRTC_V_SYNC_START, 0xff);
773 outb_p(0xff,vga_video_port_val); /* maximum value */ 737 vga_io_wcrt(VGA_CRTC_V_SYNC_END, 0x40);
774 outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ 738 /* bits 9,10 of vert. retrace */
775 outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */ 739 vga_io_wcrt(VGA_CRTC_OVERFLOW, par->vga_state.Overflow | 0x84);
776 outb_p(0x07,vga_video_port_reg); /* Overflow */
777 outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
778 } 740 }
779 741
780 if (mode & FB_BLANK_HSYNC_SUSPEND) { 742 if (mode & FB_BLANK_HSYNC_SUSPEND) {
@@ -783,29 +745,22 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
783 * <Start of horizontal Retrace> to maximum 745 * <Start of horizontal Retrace> to maximum
784 * Result: turn off horizontal sync (HSync) pulse. 746 * Result: turn off horizontal sync (HSync) pulse.
785 */ 747 */
786 outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ 748 vga_io_wcrt(VGA_CRTC_H_SYNC_START, 0xff);
787 outb_p(0xff,vga_video_port_val); /* maximum */ 749 vga_io_wcrt(VGA_CRTC_H_SYNC_END, 0x00);
788 outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */
789 outb_p(0x00,vga_video_port_val); /* minimum (0) */
790 } 750 }
791 751
792 /* restore both index registers */ 752 /* restore both index registers */
793 outb_p(SeqCtrlIndex,seq_port_reg); 753 outb_p(SeqCtrlIndex, VGA_SEQ_I);
794 outb_p(CrtCtrlIndex,vga_video_port_reg); 754 outb_p(CrtCtrlIndex, VGA_CRT_IC);
795 //sti();
796} 755}
797 756
798static void vga_vesa_unblank(struct vga16fb_par *par) 757static void vga_vesa_unblank(struct vga16fb_par *par)
799{ 758{
800 unsigned char SeqCtrlIndex; 759 unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
801 unsigned char CrtCtrlIndex; 760 unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
802 761
803 //cli();
804 SeqCtrlIndex = vga_io_r(seq_port_reg);
805 CrtCtrlIndex = vga_io_r(vga_video_port_reg);
806
807 /* restore original values of VGA controller registers */ 762 /* restore original values of VGA controller registers */
808 vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO); 763 vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
809 764
810 /* HorizontalTotal */ 765 /* HorizontalTotal */
811 vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); 766 vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
@@ -827,9 +782,8 @@ static void vga_vesa_unblank(struct vga16fb_par *par)
827 vga_io_wseq(0x01, par->vga_state.ClockingMode); 782 vga_io_wseq(0x01, par->vga_state.ClockingMode);
828 783
829 /* restore index/control registers */ 784 /* restore index/control registers */
830 vga_io_w(seq_port_reg, SeqCtrlIndex); 785 vga_io_w(VGA_SEQ_I, SeqCtrlIndex);
831 vga_io_w(vga_video_port_reg, CrtCtrlIndex); 786 vga_io_w(VGA_CRT_IC, CrtCtrlIndex);
832 //sti();
833} 787}
834 788
835static void vga_pal_blank(void) 789static void vga_pal_blank(void)
@@ -837,10 +791,10 @@ static void vga_pal_blank(void)
837 int i; 791 int i;
838 792
839 for (i=0; i<16; i++) { 793 for (i=0; i<16; i++) {
840 outb_p (i, dac_reg) ; 794 outb_p(i, VGA_PEL_IW);
841 outb_p (0, dac_val) ; 795 outb_p(0, VGA_PEL_D);
842 outb_p (0, dac_val) ; 796 outb_p(0, VGA_PEL_D);
843 outb_p (0, dac_val) ; 797 outb_p(0, VGA_PEL_D);
844 } 798 }
845} 799}
846 800
@@ -1087,12 +1041,15 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
1087 width = x2 - dx; 1041 width = x2 - dx;
1088 height = y2 - dy; 1042 height = y2 - dy;
1089 1043
1044 if (sx + dx < old_dx || sy + dy < old_dy)
1045 return;
1046
1090 /* update sx1,sy1 */ 1047 /* update sx1,sy1 */
1091 sx += (dx - old_dx); 1048 sx += (dx - old_dx);
1092 sy += (dy - old_dy); 1049 sy += (dy - old_dy);
1093 1050
1094 /* the source must be completely inside the virtual screen */ 1051 /* the source must be completely inside the virtual screen */
1095 if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres) 1052 if (sx + width > vxres || sy + height > vyres)
1096 return; 1053 return;
1097 1054
1098 switch (info->fix.type) { 1055 switch (info->fix.type) {
@@ -1363,7 +1320,6 @@ static int __init vga16fb_probe(struct platform_device *dev)
1363 printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); 1320 printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
1364 par = info->par; 1321 par = info->par;
1365 1322
1366 mutex_init(&par->open_lock);
1367 par->isVGA = screen_info.orig_video_isVGA; 1323 par->isVGA = screen_info.orig_video_isVGA;
1368 par->palette_blanked = 0; 1324 par->palette_blanked = 0;
1369 par->vesa_blanked = 0; 1325 par->vesa_blanked = 0;
@@ -1482,6 +1438,7 @@ static void __exit vga16fb_exit(void)
1482 platform_driver_unregister(&vga16fb_driver); 1438 platform_driver_unregister(&vga16fb_driver);
1483} 1439}
1484 1440
1441MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
1485MODULE_LICENSE("GPL"); 1442MODULE_LICENSE("GPL");
1486module_init(vga16fb_init); 1443module_init(vga16fb_init);
1487module_exit(vga16fb_exit); 1444module_exit(vga16fb_exit);
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
new file mode 100644
index 000000000000..e533b4b6aba4
--- /dev/null
+++ b/drivers/video/via/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
3#
4
5obj-$(CONFIG_FB_VIA) += viafb.o
6
7viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
new file mode 100644
index 000000000000..632523ff1fb7
--- /dev/null
+++ b/drivers/video/via/accel.c
@@ -0,0 +1,279 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include "global.h"
22
23void viafb_init_accel(void)
24{
25 viaparinfo->fbmem_free -= CURSOR_SIZE;
26 viaparinfo->cursor_start = viaparinfo->fbmem_free;
27 viaparinfo->fbmem_used += CURSOR_SIZE;
28
29 /* Reverse 8*1024 memory space for cursor image */
30 viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE);
31 viaparinfo->VQ_start = viaparinfo->fbmem_free;
32 viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1;
33 viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); }
34
35void viafb_init_2d_engine(void)
36{
37 u32 dwVQStartAddr, dwVQEndAddr;
38 u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH;
39
40 /* init 2D engine regs to reset 2D engine */
41 writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE);
42 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
43 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS);
44 writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION);
45 writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR);
46 writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR);
47 writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR);
48 writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL);
49 writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR);
50 writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET);
51 writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL);
52 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
53 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
54 writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH);
55 writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1);
56
57 /* Init AGP and VQ regs */
58 switch (viaparinfo->chip_info->gfx_chip_name) {
59 case UNICHROME_K8M890:
60 case UNICHROME_P4M900:
61 writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET);
62 writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
63 writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
64 break;
65
66 default:
67 writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET);
68 writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
69 writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE);
70 writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
71 writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
72 writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
73 writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
74 writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
75 writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
76
77 writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET);
78 writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
79 break;
80 }
81 if (viaparinfo->VQ_start != 0) {
82 /* Enable VQ */
83 dwVQStartAddr = viaparinfo->VQ_start;
84 dwVQEndAddr = viaparinfo->VQ_end;
85
86 dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF);
87 dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF);
88 dwVQStartEndH = 0x52000000 |
89 ((dwVQStartAddr & 0xFF000000) >> 24) |
90 ((dwVQEndAddr & 0xFF000000) >> 16);
91 dwVQLen = 0x53000000 | (VQ_SIZE >> 3);
92 switch (viaparinfo->chip_info->gfx_chip_name) {
93 case UNICHROME_K8M890:
94 case UNICHROME_P4M900:
95 dwVQStartL |= 0x20000000;
96 dwVQEndL |= 0x20000000;
97 dwVQStartEndH |= 0x20000000;
98 dwVQLen |= 0x20000000;
99 break;
100 default:
101 break;
102 }
103
104 switch (viaparinfo->chip_info->gfx_chip_name) {
105 case UNICHROME_K8M890:
106 case UNICHROME_P4M900:
107 writel(0x00100000,
108 viaparinfo->io_virt + VIA_REG_CR_TRANSET);
109 writel(dwVQStartEndH,
110 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
111 writel(dwVQStartL,
112 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
113 writel(dwVQEndL,
114 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
115 writel(dwVQLen,
116 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
117 writel(0x74301001,
118 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
119 writel(0x00000000,
120 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
121 break;
122 default:
123 writel(0x00FE0000,
124 viaparinfo->io_virt + VIA_REG_TRANSET);
125 writel(0x080003FE,
126 viaparinfo->io_virt + VIA_REG_TRANSPACE);
127 writel(0x0A00027C,
128 viaparinfo->io_virt + VIA_REG_TRANSPACE);
129 writel(0x0B000260,
130 viaparinfo->io_virt + VIA_REG_TRANSPACE);
131 writel(0x0C000274,
132 viaparinfo->io_virt + VIA_REG_TRANSPACE);
133 writel(0x0D000264,
134 viaparinfo->io_virt + VIA_REG_TRANSPACE);
135 writel(0x0E000000,
136 viaparinfo->io_virt + VIA_REG_TRANSPACE);
137 writel(0x0F000020,
138 viaparinfo->io_virt + VIA_REG_TRANSPACE);
139 writel(0x1000027E,
140 viaparinfo->io_virt + VIA_REG_TRANSPACE);
141 writel(0x110002FE,
142 viaparinfo->io_virt + VIA_REG_TRANSPACE);
143 writel(0x200F0060,
144 viaparinfo->io_virt + VIA_REG_TRANSPACE);
145
146 writel(0x00000006,
147 viaparinfo->io_virt + VIA_REG_TRANSPACE);
148 writel(0x40008C0F,
149 viaparinfo->io_virt + VIA_REG_TRANSPACE);
150 writel(0x44000000,
151 viaparinfo->io_virt + VIA_REG_TRANSPACE);
152 writel(0x45080C04,
153 viaparinfo->io_virt + VIA_REG_TRANSPACE);
154 writel(0x46800408,
155 viaparinfo->io_virt + VIA_REG_TRANSPACE);
156
157 writel(dwVQStartEndH,
158 viaparinfo->io_virt + VIA_REG_TRANSPACE);
159 writel(dwVQStartL,
160 viaparinfo->io_virt + VIA_REG_TRANSPACE);
161 writel(dwVQEndL,
162 viaparinfo->io_virt + VIA_REG_TRANSPACE);
163 writel(dwVQLen,
164 viaparinfo->io_virt + VIA_REG_TRANSPACE);
165 break;
166 }
167 } else {
168 /* Disable VQ */
169 switch (viaparinfo->chip_info->gfx_chip_name) {
170 case UNICHROME_K8M890:
171 case UNICHROME_P4M900:
172 writel(0x00100000,
173 viaparinfo->io_virt + VIA_REG_CR_TRANSET);
174 writel(0x74301000,
175 viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
176 break;
177 default:
178 writel(0x00FE0000,
179 viaparinfo->io_virt + VIA_REG_TRANSET);
180 writel(0x00000004,
181 viaparinfo->io_virt + VIA_REG_TRANSPACE);
182 writel(0x40008C0F,
183 viaparinfo->io_virt + VIA_REG_TRANSPACE);
184 writel(0x44000000,
185 viaparinfo->io_virt + VIA_REG_TRANSPACE);
186 writel(0x45080C04,
187 viaparinfo->io_virt + VIA_REG_TRANSPACE);
188 writel(0x46800408,
189 viaparinfo->io_virt + VIA_REG_TRANSPACE);
190 break;
191 }
192 }
193
194 viafb_set_2d_color_depth(viaparinfo->bpp);
195
196 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
197 writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
198
199 writel(VIA_PITCH_ENABLE |
200 (((viaparinfo->hres *
201 viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres *
202 viaparinfo->
203 bpp >> 3) >> 3) << 16)),
204 viaparinfo->io_virt + VIA_REG_PITCH);
205}
206
207void viafb_set_2d_color_depth(int bpp)
208{
209 u32 dwGEMode;
210
211 dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF;
212
213 switch (bpp) {
214 case 16:
215 dwGEMode |= VIA_GEM_16bpp;
216 break;
217 case 32:
218 dwGEMode |= VIA_GEM_32bpp;
219 break;
220 default:
221 dwGEMode |= VIA_GEM_8bpp;
222 break;
223 }
224
225 /* Set BPP and Pitch */
226 writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE);
227}
228
229void viafb_hw_cursor_init(void)
230{
231 /* Set Cursor Image Base Address */
232 writel(viaparinfo->cursor_start,
233 viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
234 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
235 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
236 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
237 writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
238}
239
240void viafb_show_hw_cursor(struct fb_info *info, int Status)
241{
242 u32 temp;
243 u32 iga_path = ((struct viafb_par *)(info->par))->iga_path;
244
245 temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
246 switch (Status) {
247 case HW_Cursor_ON:
248 temp |= 0x1;
249 break;
250 case HW_Cursor_OFF:
251 temp &= 0xFFFFFFFE;
252 break;
253 }
254 switch (iga_path) {
255 case IGA2:
256 temp |= 0x80000000;
257 break;
258 case IGA1:
259 default:
260 temp &= 0x7FFFFFFF;
261 }
262 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
263}
264
265int viafb_wait_engine_idle(void)
266{
267 int loop = 0;
268
269 while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) &
270 VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP))
271 cpu_relax();
272
273 while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) &
274 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
275 (loop++ < MAXLOOP))
276 cpu_relax();
277
278 return loop >= MAXLOOP;
279}
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
new file mode 100644
index 000000000000..29bf854e8ccf
--- /dev/null
+++ b/drivers/video/via/accel.h
@@ -0,0 +1,169 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __ACCEL_H__
23#define __ACCEL_H__
24
25#define FB_ACCEL_VIA_UNICHROME 50
26
27/* MMIO Base Address Definition */
28#define MMIO_VGABASE 0x8000
29#define MMIO_CR_READ (MMIO_VGABASE + 0x3D4)
30#define MMIO_CR_WRITE (MMIO_VGABASE + 0x3D5)
31#define MMIO_SR_READ (MMIO_VGABASE + 0x3C4)
32#define MMIO_SR_WRITE (MMIO_VGABASE + 0x3C5)
33
34/* HW Cursor Status Define */
35#define HW_Cursor_ON 0
36#define HW_Cursor_OFF 1
37
38#define CURSOR_SIZE (8 * 1024)
39#define VQ_SIZE (256 * 1024)
40
41#define VIA_MMIO_BLTBASE 0x200000
42#define VIA_MMIO_BLTSIZE 0x200000
43
44/* Defines for 2D registers */
45#define VIA_REG_GECMD 0x000
46#define VIA_REG_GEMODE 0x004
47#define VIA_REG_SRCPOS 0x008
48#define VIA_REG_DSTPOS 0x00C
49/* width and height */
50#define VIA_REG_DIMENSION 0x010
51#define VIA_REG_PATADDR 0x014
52#define VIA_REG_FGCOLOR 0x018
53#define VIA_REG_BGCOLOR 0x01C
54/* top and left of clipping */
55#define VIA_REG_CLIPTL 0x020
56/* bottom and right of clipping */
57#define VIA_REG_CLIPBR 0x024
58#define VIA_REG_OFFSET 0x028
59/* color key control */
60#define VIA_REG_KEYCONTROL 0x02C
61#define VIA_REG_SRCBASE 0x030
62#define VIA_REG_DSTBASE 0x034
63/* pitch of src and dst */
64#define VIA_REG_PITCH 0x038
65#define VIA_REG_MONOPAT0 0x03C
66#define VIA_REG_MONOPAT1 0x040
67/* from 0x100 to 0x1ff */
68#define VIA_REG_COLORPAT 0x100
69
70/* VIA_REG_PITCH(0x38): Pitch Setting */
71#define VIA_PITCH_ENABLE 0x80000000
72
73/* defines for VIA HW cursor registers */
74#define VIA_REG_CURSOR_MODE 0x2D0
75#define VIA_REG_CURSOR_POS 0x2D4
76#define VIA_REG_CURSOR_ORG 0x2D8
77#define VIA_REG_CURSOR_BG 0x2DC
78#define VIA_REG_CURSOR_FG 0x2E0
79
80/* VIA_REG_GEMODE(0x04): GE mode */
81#define VIA_GEM_8bpp 0x00000000
82#define VIA_GEM_16bpp 0x00000100
83#define VIA_GEM_32bpp 0x00000300
84
85/* VIA_REG_GECMD(0x00): 2D Engine Command */
86#define VIA_GEC_NOOP 0x00000000
87#define VIA_GEC_BLT 0x00000001
88#define VIA_GEC_LINE 0x00000005
89
90/* Rotate Command */
91#define VIA_GEC_ROT 0x00000008
92
93#define VIA_GEC_SRC_XY 0x00000000
94#define VIA_GEC_SRC_LINEAR 0x00000010
95#define VIA_GEC_DST_XY 0x00000000
96#define VIA_GEC_DST_LINRAT 0x00000020
97
98#define VIA_GEC_SRC_FB 0x00000000
99#define VIA_GEC_SRC_SYS 0x00000040
100#define VIA_GEC_DST_FB 0x00000000
101#define VIA_GEC_DST_SYS 0x00000080
102
103/* source is mono */
104#define VIA_GEC_SRC_MONO 0x00000100
105/* pattern is mono */
106#define VIA_GEC_PAT_MONO 0x00000200
107/* mono src is opaque */
108#define VIA_GEC_MSRC_OPAQUE 0x00000000
109/* mono src is transparent */
110#define VIA_GEC_MSRC_TRANS 0x00000400
111/* pattern is in frame buffer */
112#define VIA_GEC_PAT_FB 0x00000000
113/* pattern is from reg setting */
114#define VIA_GEC_PAT_REG 0x00000800
115
116#define VIA_GEC_CLIP_DISABLE 0x00000000
117#define VIA_GEC_CLIP_ENABLE 0x00001000
118
119#define VIA_GEC_FIXCOLOR_PAT 0x00002000
120
121#define VIA_GEC_INCX 0x00000000
122#define VIA_GEC_DECY 0x00004000
123#define VIA_GEC_INCY 0x00000000
124#define VIA_GEC_DECX 0x00008000
125/* mono pattern is opaque */
126#define VIA_GEC_MPAT_OPAQUE 0x00000000
127/* mono pattern is transparent */
128#define VIA_GEC_MPAT_TRANS 0x00010000
129
130#define VIA_GEC_MONO_UNPACK 0x00000000
131#define VIA_GEC_MONO_PACK 0x00020000
132#define VIA_GEC_MONO_DWORD 0x00000000
133#define VIA_GEC_MONO_WORD 0x00040000
134#define VIA_GEC_MONO_BYTE 0x00080000
135
136#define VIA_GEC_LASTPIXEL_ON 0x00000000
137#define VIA_GEC_LASTPIXEL_OFF 0x00100000
138#define VIA_GEC_X_MAJOR 0x00000000
139#define VIA_GEC_Y_MAJOR 0x00200000
140#define VIA_GEC_QUICK_START 0x00800000
141
142/* defines for VIA 3D registers */
143#define VIA_REG_STATUS 0x400
144#define VIA_REG_CR_TRANSET 0x41C
145#define VIA_REG_CR_TRANSPACE 0x420
146#define VIA_REG_TRANSET 0x43C
147#define VIA_REG_TRANSPACE 0x440
148
149/* VIA_REG_STATUS(0x400): Engine Status */
150
151/* Command Regulator is busy */
152#define VIA_CMD_RGTR_BUSY 0x00000080
153/* 2D Engine is busy */
154#define VIA_2D_ENG_BUSY 0x00000002
155/* 3D Engine is busy */
156#define VIA_3D_ENG_BUSY 0x00000001
157/* Virtual Queue is busy */
158#define VIA_VR_QUEUE_BUSY 0x00020000
159
160#define MAXLOOP 0xFFFFFF
161
162void viafb_init_accel(void);
163void viafb_init_2d_engine(void);
164void set_2d_color_depth(int);
165void viafb_hw_cursor_init(void);
166void viafb_show_hw_cursor(struct fb_info *info, int Status); int
167viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp);
168
169#endif /* __ACCEL_H__ */
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
new file mode 100644
index 000000000000..dde95edc387a
--- /dev/null
+++ b/drivers/video/via/chip.h
@@ -0,0 +1,190 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __CHIP_H__
22#define __CHIP_H__
23
24#include "global.h"
25
26/***************************************/
27/* Definition Graphic Chip Information */
28/***************************************/
29
30#define PCI_VIA_VENDOR_ID 0x1106
31
32/* Define VIA Graphic Chip Name */
33#define UNICHROME_CLE266 1
34#define UNICHROME_CLE266_DID 0x3122
35#define CLE266_REVISION_AX 0x0A
36#define CLE266_REVISION_CX 0x0C
37
38#define UNICHROME_K400 2
39#define UNICHROME_K400_DID 0x7205
40
41#define UNICHROME_K800 3
42#define UNICHROME_K800_DID 0x3108
43
44#define UNICHROME_PM800 4
45#define UNICHROME_PM800_DID 0x3118
46
47#define UNICHROME_CN700 5
48#define UNICHROME_CN700_DID 0x3344
49
50#define UNICHROME_CX700 6
51#define UNICHROME_CX700_DID 0x3157
52#define CX700_REVISION_700 0x0
53#define CX700_REVISION_700M 0x1
54#define CX700_REVISION_700M2 0x2
55
56#define UNICHROME_CN750 7
57#define UNICHROME_CN750_DID 0x3225
58
59#define UNICHROME_K8M890 8
60#define UNICHROME_K8M890_DID 0x3230
61
62#define UNICHROME_P4M890 9
63#define UNICHROME_P4M890_DID 0x3343
64
65#define UNICHROME_P4M900 10
66#define UNICHROME_P4M900_DID 0x3371
67
68#define UNICHROME_VX800 11
69#define UNICHROME_VX800_DID 0x1122
70
71/**************************************************/
72/* Definition TMDS Trasmitter Information */
73/**************************************************/
74
75/* Definition TMDS Trasmitter Index */
76#define NON_TMDS_TRANSMITTER 0x00
77#define VT1632_TMDS 0x01
78#define INTEGRATED_TMDS 0x42
79
80/* Definition TMDS Trasmitter I2C Slave Address */
81#define VT1632_TMDS_I2C_ADDR 0x10
82
83/**************************************************/
84/* Definition LVDS Trasmitter Information */
85/**************************************************/
86
87/* Definition LVDS Trasmitter Index */
88#define NON_LVDS_TRANSMITTER 0x00
89#define VT1631_LVDS 0x01
90#define VT1636_LVDS 0x0E
91#define INTEGRATED_LVDS 0x41
92
93/* Definition Digital Transmitter Mode */
94#define TX_DATA_12_BITS 0x01
95#define TX_DATA_24_BITS 0x02
96#define TX_DATA_DDR_MODE 0x04
97#define TX_DATA_SDR_MODE 0x08
98
99/* Definition LVDS Trasmitter I2C Slave Address */
100#define VT1631_LVDS_I2C_ADDR 0x70
101#define VT3271_LVDS_I2C_ADDR 0x80
102#define VT1636_LVDS_I2C_ADDR 0x80
103
104struct tmds_chip_information {
105 int tmds_chip_name;
106 int tmds_chip_slave_addr;
107 int dvi_panel_id;
108 int data_mode;
109 int output_interface;
110 int i2c_port;
111 int device_type;
112};
113
114struct lvds_chip_information {
115 int lvds_chip_name;
116 int lvds_chip_slave_addr;
117 int data_mode;
118 int output_interface;
119 int i2c_port;
120};
121
122struct chip_information {
123 int gfx_chip_name;
124 int gfx_chip_revision;
125 int chip_on_slot;
126 struct tmds_chip_information tmds_chip_info;
127 struct lvds_chip_information lvds_chip_info;
128 struct lvds_chip_information lvds_chip_info2;
129};
130
131struct crt_setting_information {
132 int iga_path;
133 int h_active;
134 int v_active;
135 int bpp;
136 int refresh_rate;
137};
138
139struct tmds_setting_information {
140 int iga_path;
141 int h_active;
142 int v_active;
143 int bpp;
144 int refresh_rate;
145 int get_dvi_size_method;
146 int max_pixel_clock;
147 int dvi_panel_size;
148 int dvi_panel_hres;
149 int dvi_panel_vres;
150 int native_size;
151};
152
153struct lvds_setting_information {
154 int iga_path;
155 int h_active;
156 int v_active;
157 int bpp;
158 int refresh_rate;
159 int get_lcd_size_method;
160 int lcd_panel_id;
161 int lcd_panel_size;
162 int lcd_panel_hres;
163 int lcd_panel_vres;
164 int display_method;
165 int device_lcd_dualedge;
166 int LCDDithering;
167 int lcd_mode;
168 u32 vclk; /*panel mode clock value */
169};
170
171struct GFX_DPA_SETTING {
172 int ClkRangeIndex;
173 u8 DVP0; /* CR96[3:0] */
174 u8 DVP0DataDri_S1; /* SR2A[5] */
175 u8 DVP0DataDri_S; /* SR1B[1] */
176 u8 DVP0ClockDri_S1; /* SR2A[4] */
177 u8 DVP0ClockDri_S; /* SR1E[2] */
178 u8 DVP1; /* CR9B[3:0] */
179 u8 DVP1Driving; /* SR65[3:0], Data and Clock driving */
180 u8 DFPHigh; /* CR97[3:0] */
181 u8 DFPLow; /* CR99[3:0] */
182
183};
184
185struct VT1636_DPA_SETTING {
186 int PanelSizeID;
187 u8 CLK_SEL_ST1;
188 u8 CLK_SEL_ST2;
189};
190#endif /* __CHIP_H__ */
diff --git a/drivers/video/via/debug.h b/drivers/video/via/debug.h
new file mode 100644
index 000000000000..86eacc2017f3
--- /dev/null
+++ b/drivers/video/via/debug.h
@@ -0,0 +1,41 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __DEBUG_H__
22#define __DEBUG_H__
23
24#ifndef VIAFB_DEBUG
25#define VIAFB_DEBUG 0
26#endif
27
28#if VIAFB_DEBUG
29#define DEBUG_MSG(f, a...) printk(f, ## a)
30#else
31#define DEBUG_MSG(f, a...)
32#endif
33
34#define VIAFB_WARN 0
35#if VIAFB_WARN
36#define WARN_MSG(f, a...) printk(f, ## a)
37#else
38#define WARN_MSG(f, a...)
39#endif
40
41#endif /* __DEBUG_H__ */
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
new file mode 100644
index 000000000000..d6965447ca69
--- /dev/null
+++ b/drivers/video/via/dvi.c
@@ -0,0 +1,682 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include "global.h"
22
23static void tmds_register_write(int index, u8 data);
24static int tmds_register_read(int index);
25static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
26static int check_reduce_blanking_mode(int mode_index,
27 int refresh_rate);
28static int dvi_get_panel_size_from_DDCv1(void);
29static int dvi_get_panel_size_from_DDCv2(void);
30static unsigned char dvi_get_panel_info(void);
31static int viafb_dvi_query_EDID(void);
32
33static int check_tmds_chip(int device_id_subaddr, int device_id)
34{
35 if (tmds_register_read(device_id_subaddr) == device_id)
36 return OK;
37 else
38 return FAIL;
39}
40
41void viafb_init_dvi_size(void)
42{
43 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
44 DEBUG_MSG(KERN_INFO
45 "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n",
46 viaparinfo->tmds_setting_info->get_dvi_size_method);
47
48 switch (viaparinfo->tmds_setting_info->get_dvi_size_method) {
49 case GET_DVI_SIZE_BY_SYSTEM_BIOS:
50 break;
51 case GET_DVI_SZIE_BY_HW_STRAPPING:
52 break;
53 case GET_DVI_SIZE_BY_VGA_BIOS:
54 default:
55 dvi_get_panel_info();
56 break;
57 }
58 return;
59}
60
61int viafb_tmds_trasmitter_identify(void)
62{
63 unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
64
65 /* Turn on ouputting pad */
66 switch (viaparinfo->chip_info->gfx_chip_name) {
67 case UNICHROME_K8M890:
68 /*=* DFP Low Pad on *=*/
69 sr2a = viafb_read_reg(VIASR, SR2A);
70 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
71 break;
72
73 case UNICHROME_P4M900:
74 case UNICHROME_P4M890:
75 /* DFP Low Pad on */
76 sr2a = viafb_read_reg(VIASR, SR2A);
77 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
78 /* DVP0 Pad on */
79 sr1e = viafb_read_reg(VIASR, SR1E);
80 viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
81 break;
82
83 default:
84 /* DVP0/DVP1 Pad on */
85 sr1e = viafb_read_reg(VIASR, SR1E);
86 viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
87 BIT5 + BIT6 + BIT7);
88 /* SR3E[1]Multi-function selection:
89 0 = Emulate I2C and DDC bus by GPIO2/3/4. */
90 sr3e = viafb_read_reg(VIASR, SR3E);
91 viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
92 break;
93 }
94
95 /* Check for VT1632: */
96 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
97 viaparinfo->chip_info->
98 tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
99 viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX;
100 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) {
101 /*
102 * Currently only support 12bits,dual edge,add 24bits mode later
103 */
104 tmds_register_write(0x08, 0x3b);
105
106 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
107 DEBUG_MSG(KERN_INFO "\n %2d",
108 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
109 DEBUG_MSG(KERN_INFO "\n %2d",
110 viaparinfo->chip_info->tmds_chip_info.i2c_port);
111 return OK;
112 } else {
113 viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX;
114 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)
115 != FAIL) {
116 tmds_register_write(0x08, 0x3b);
117 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
118 DEBUG_MSG(KERN_INFO "\n %2d",
119 viaparinfo->chip_info->
120 tmds_chip_info.tmds_chip_name);
121 DEBUG_MSG(KERN_INFO "\n %2d",
122 viaparinfo->chip_info->
123 tmds_chip_info.i2c_port);
124 return OK;
125 }
126 }
127
128 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
129
130 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
131 ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
132 (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
133 DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
134 return OK;
135 }
136
137 switch (viaparinfo->chip_info->gfx_chip_name) {
138 case UNICHROME_K8M890:
139 viafb_write_reg(SR2A, VIASR, sr2a);
140 break;
141
142 case UNICHROME_P4M900:
143 case UNICHROME_P4M890:
144 viafb_write_reg(SR2A, VIASR, sr2a);
145 viafb_write_reg(SR1E, VIASR, sr1e);
146 break;
147
148 default:
149 viafb_write_reg(SR1E, VIASR, sr1e);
150 viafb_write_reg(SR3E, VIASR, sr3e);
151 break;
152 }
153
154 viaparinfo->chip_info->
155 tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
156 viaparinfo->chip_info->tmds_chip_info.
157 tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
158 return FAIL;
159}
160
161static void tmds_register_write(int index, u8 data)
162{
163 viaparinfo->i2c_stuff.i2c_port =
164 viaparinfo->chip_info->tmds_chip_info.i2c_port;
165
166 viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.
167 tmds_chip_slave_addr, index,
168 data);
169}
170
171static int tmds_register_read(int index)
172{
173 u8 data;
174
175 viaparinfo->i2c_stuff.i2c_port =
176 viaparinfo->chip_info->tmds_chip_info.i2c_port;
177 viafb_i2c_readbyte((u8) viaparinfo->chip_info->
178 tmds_chip_info.tmds_chip_slave_addr,
179 (u8) index, &data);
180 return data;
181}
182
183static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
184{
185 viaparinfo->i2c_stuff.i2c_port =
186 viaparinfo->chip_info->tmds_chip_info.i2c_port;
187 viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info.
188 tmds_chip_slave_addr, (u8) index, buff, buff_len);
189 return 0;
190}
191
192static int check_reduce_blanking_mode(int mode_index,
193 int refresh_rate)
194{
195 if (refresh_rate != 60)
196 return false;
197
198 switch (mode_index) {
199 /* Following modes have reduce blanking mode. */
200 case VIA_RES_1360X768:
201 case VIA_RES_1400X1050:
202 case VIA_RES_1440X900:
203 case VIA_RES_1600X900:
204 case VIA_RES_1680X1050:
205 case VIA_RES_1920X1080:
206 case VIA_RES_1920X1200:
207 break;
208
209 default:
210 DEBUG_MSG(KERN_INFO
211 "This dvi mode %d have no reduce blanking mode!\n",
212 mode_index);
213 return false;
214 }
215
216 return true;
217}
218
219/* DVI Set Mode */
220void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga)
221{
222 struct VideoModeTable *videoMode = NULL;
223 struct crt_mode_table *pDviTiming;
224 unsigned long desirePixelClock, maxPixelClock;
225 int status = 0;
226 videoMode = viafb_get_modetbl_pointer(video_index);
227 pDviTiming = videoMode->crtc;
228 desirePixelClock = pDviTiming->clk / 1000000;
229 maxPixelClock = (unsigned long)viaparinfo->
230 tmds_setting_info->max_pixel_clock;
231
232 DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
233
234 if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
235 /*Check if reduce-blanking mode is exist */
236 status =
237 check_reduce_blanking_mode(video_index,
238 pDviTiming->refresh_rate);
239 if (status) {
240 video_index += 100; /*Use reduce-blanking mode */
241 videoMode = viafb_get_modetbl_pointer(video_index);
242 pDviTiming = videoMode->crtc;
243 DEBUG_MSG(KERN_INFO
244 "DVI use reduce blanking mode %d!!\n",
245 video_index);
246 }
247 }
248 viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga);
249 viafb_set_output_path(DEVICE_DVI, set_iga,
250 viaparinfo->chip_info->tmds_chip_info.output_interface);
251}
252
253/* Sense DVI Connector */
254int viafb_dvi_sense(void)
255{
256 u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
257 RegCR93 = 0, RegCR9B = 0, data;
258 int ret = false;
259
260 DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
261
262 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
263 /* DI1 Pad on */
264 RegSR1E = viafb_read_reg(VIASR, SR1E);
265 viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
266
267 /* CR6B[0]VCK Input Selection: 1 = External clock. */
268 RegCR6B = viafb_read_reg(VIACR, CR6B);
269 viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
270
271 /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
272 [0] Software Control Power Sequence */
273 RegCR91 = viafb_read_reg(VIACR, CR91);
274 viafb_write_reg(CR91, VIACR, 0x1D);
275
276 /* CR93[7] DI1 Data Source Selection: 1 = DSP2.
277 CR93[5] DI1 Clock Source: 1 = internal.
278 CR93[4] DI1 Clock Polarity.
279 CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
280 RegCR93 = viafb_read_reg(VIACR, CR93);
281 viafb_write_reg(CR93, VIACR, 0x01);
282 } else {
283 /* DVP0/DVP1 Pad on */
284 RegSR1E = viafb_read_reg(VIASR, SR1E);
285 viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
286
287 /* SR3E[1]Multi-function selection:
288 0 = Emulate I2C and DDC bus by GPIO2/3/4. */
289 RegSR3E = viafb_read_reg(VIASR, SR3E);
290 viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
291
292 /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
293 [0] Software Control Power Sequence */
294 RegCR91 = viafb_read_reg(VIACR, CR91);
295 viafb_write_reg(CR91, VIACR, 0x1D);
296
297 /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
298 display.CR9B[2:0] DVP1 Clock Adjust */
299 RegCR9B = viafb_read_reg(VIACR, CR9B);
300 viafb_write_reg(CR9B, VIACR, 0x01);
301 }
302
303 data = (u8) tmds_register_read(0x09);
304 if (data & 0x04)
305 ret = true;
306
307 if (ret == false) {
308 if (viafb_dvi_query_EDID())
309 ret = true;
310 }
311
312 /* Restore status */
313 viafb_write_reg(SR1E, VIASR, RegSR1E);
314 viafb_write_reg(CR91, VIACR, RegCR91);
315 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
316 viafb_write_reg(CR6B, VIACR, RegCR6B);
317 viafb_write_reg(CR93, VIACR, RegCR93);
318 } else {
319 viafb_write_reg(SR3E, VIASR, RegSR3E);
320 viafb_write_reg(CR9B, VIACR, RegCR9B);
321 }
322
323 return ret;
324}
325
326/* Query Flat Panel's EDID Table Version Through DVI Connector */
327static int viafb_dvi_query_EDID(void)
328{
329 u8 data0, data1;
330 int restore;
331
332 DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
333
334 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
335 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
336
337 data0 = (u8) tmds_register_read(0x00);
338 data1 = (u8) tmds_register_read(0x01);
339 if ((data0 == 0) && (data1 == 0xFF)) {
340 viaparinfo->chip_info->
341 tmds_chip_info.tmds_chip_slave_addr = restore;
342 return EDID_VERSION_1; /* Found EDID1 Table */
343 }
344
345 data0 = (u8) tmds_register_read(0x00);
346 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
347 if (data0 == 0x20)
348 return EDID_VERSION_2; /* Found EDID2 Table */
349 else
350 return false;
351}
352
353/*
354 *
355 * int dvi_get_panel_size_from_DDCv1(void)
356 *
357 * - Get Panel Size Using EDID1 Table
358 *
359 * Return Type: int
360 *
361 */
362static int dvi_get_panel_size_from_DDCv1(void)
363{
364 int i, max_h = 0, max_v = 0, tmp, restore;
365 unsigned char rData;
366 unsigned char EDID_DATA[18];
367
368 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
369
370 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
371 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
372
373 rData = tmds_register_read(0x23);
374 if (rData & 0x3C)
375 max_h = 640;
376 if (rData & 0xC0)
377 max_h = 720;
378 if (rData & 0x03)
379 max_h = 800;
380
381 rData = tmds_register_read(0x24);
382 if (rData & 0xC0)
383 max_h = 800;
384 if (rData & 0x1E)
385 max_h = 1024;
386 if (rData & 0x01)
387 max_h = 1280;
388
389 for (i = 0x25; i < 0x6D; i++) {
390 switch (i) {
391 case 0x26:
392 case 0x28:
393 case 0x2A:
394 case 0x2C:
395 case 0x2E:
396 case 0x30:
397 case 0x32:
398 case 0x34:
399 rData = tmds_register_read(i);
400 if (rData == 1)
401 break;
402 /* data = (data + 31) * 8 */
403 tmp = (rData + 31) << 3;
404 if (tmp > max_h)
405 max_h = tmp;
406 break;
407
408 case 0x36:
409 case 0x48:
410 case 0x5A:
411 case 0x6C:
412 tmds_register_read_bytes(i, EDID_DATA, 10);
413 if (!(EDID_DATA[0] || EDID_DATA[1])) {
414 /* The first two byte must be zero. */
415 if (EDID_DATA[3] == 0xFD) {
416 /* To get max pixel clock. */
417 viaparinfo->tmds_setting_info->
418 max_pixel_clock = EDID_DATA[9] * 10;
419 }
420 }
421 break;
422
423 default:
424 break;
425 }
426 }
427
428 switch (max_h) {
429 case 640:
430 viaparinfo->tmds_setting_info->dvi_panel_size =
431 VIA_RES_640X480;
432 break;
433 case 800:
434 viaparinfo->tmds_setting_info->dvi_panel_size =
435 VIA_RES_800X600;
436 break;
437 case 1024:
438 viaparinfo->tmds_setting_info->dvi_panel_size =
439 VIA_RES_1024X768;
440 break;
441 case 1280:
442 viaparinfo->tmds_setting_info->dvi_panel_size =
443 VIA_RES_1280X1024;
444 break;
445 case 1400:
446 viaparinfo->tmds_setting_info->dvi_panel_size =
447 VIA_RES_1400X1050;
448 break;
449 case 1440:
450 viaparinfo->tmds_setting_info->dvi_panel_size =
451 VIA_RES_1440X1050;
452 break;
453 case 1600:
454 viaparinfo->tmds_setting_info->dvi_panel_size =
455 VIA_RES_1600X1200;
456 break;
457 case 1920:
458 if (max_v == 1200) {
459 viaparinfo->tmds_setting_info->dvi_panel_size =
460 VIA_RES_1920X1200;
461 } else {
462 viaparinfo->tmds_setting_info->dvi_panel_size =
463 VIA_RES_1920X1080;
464 }
465
466 break;
467 default:
468 viaparinfo->tmds_setting_info->dvi_panel_size =
469 VIA_RES_1024X768;
470 DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\
471 set default panel size.\n", max_h);
472 break;
473 }
474
475 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
476 viaparinfo->tmds_setting_info->max_pixel_clock);
477 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
478 return viaparinfo->tmds_setting_info->dvi_panel_size;
479}
480
481/*
482 *
483 * int dvi_get_panel_size_from_DDCv2(void)
484 *
485 * - Get Panel Size Using EDID2 Table
486 *
487 * Return Type: int
488 *
489 */
490static int dvi_get_panel_size_from_DDCv2(void)
491{
492 int HSize = 0, restore;
493 unsigned char R_Buffer[2];
494
495 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
496
497 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
498 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2;
499
500 /* Horizontal: 0x76, 0x77 */
501 tmds_register_read_bytes(0x76, R_Buffer, 2);
502 HSize = R_Buffer[0];
503 HSize += R_Buffer[1] << 8;
504
505 switch (HSize) {
506 case 640:
507 viaparinfo->tmds_setting_info->dvi_panel_size =
508 VIA_RES_640X480;
509 break;
510 case 800:
511 viaparinfo->tmds_setting_info->dvi_panel_size =
512 VIA_RES_800X600;
513 break;
514 case 1024:
515 viaparinfo->tmds_setting_info->dvi_panel_size =
516 VIA_RES_1024X768;
517 break;
518 case 1280:
519 viaparinfo->tmds_setting_info->dvi_panel_size =
520 VIA_RES_1280X1024;
521 break;
522 case 1400:
523 viaparinfo->tmds_setting_info->dvi_panel_size =
524 VIA_RES_1400X1050;
525 break;
526 case 1440:
527 viaparinfo->tmds_setting_info->dvi_panel_size =
528 VIA_RES_1440X1050;
529 break;
530 case 1600:
531 viaparinfo->tmds_setting_info->dvi_panel_size =
532 VIA_RES_1600X1200;
533 break;
534 default:
535 viaparinfo->tmds_setting_info->dvi_panel_size =
536 VIA_RES_1024X768;
537 DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\
538 set default panel size.\n", HSize);
539 break;
540 }
541
542 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
543 return viaparinfo->tmds_setting_info->dvi_panel_size;
544}
545
546/*
547 *
548 * unsigned char dvi_get_panel_info(void)
549 *
550 * - Get Panel Size
551 *
552 * Return Type: unsigned char
553 */
554static unsigned char dvi_get_panel_info(void)
555{
556 unsigned char dvipanelsize;
557 DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n");
558
559 viafb_dvi_sense();
560 switch (viafb_dvi_query_EDID()) {
561 case 1:
562 dvi_get_panel_size_from_DDCv1();
563 break;
564 case 2:
565 dvi_get_panel_size_from_DDCv2();
566 break;
567 default:
568 break;
569 }
570
571 DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n",
572 viaparinfo->tmds_setting_info->dvi_panel_size);
573 dvipanelsize = (unsigned char)(viaparinfo->
574 tmds_setting_info->dvi_panel_size);
575 return dvipanelsize;
576}
577
578/* If Disable DVI, turn off pad */
579void viafb_dvi_disable(void)
580{
581 if (viaparinfo->chip_info->
582 tmds_chip_info.output_interface == INTERFACE_DVP0)
583 viafb_write_reg(SR1E, VIASR,
584 viafb_read_reg(VIASR, SR1E) & (~0xC0));
585
586 if (viaparinfo->chip_info->
587 tmds_chip_info.output_interface == INTERFACE_DVP1)
588 viafb_write_reg(SR1E, VIASR,
589 viafb_read_reg(VIASR, SR1E) & (~0x30));
590
591 if (viaparinfo->chip_info->
592 tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
593 viafb_write_reg(SR2A, VIASR,
594 viafb_read_reg(VIASR, SR2A) & (~0x0C));
595
596 if (viaparinfo->chip_info->
597 tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
598 viafb_write_reg(SR2A, VIASR,
599 viafb_read_reg(VIASR, SR2A) & (~0x03));
600
601 if (viaparinfo->chip_info->
602 tmds_chip_info.output_interface == INTERFACE_TMDS)
603 /* Turn off TMDS power. */
604 viafb_write_reg(CRD2, VIACR,
605 viafb_read_reg(VIACR, CRD2) | 0x08);
606}
607
608/* If Enable DVI, turn off pad */
609void viafb_dvi_enable(void)
610{
611 u8 data;
612
613 if (viaparinfo->chip_info->
614 tmds_chip_info.output_interface == INTERFACE_DVP0) {
615 viafb_write_reg(SR1E, VIASR,
616 viafb_read_reg(VIASR, SR1E) | 0xC0);
617 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
618 tmds_register_write(0x88, 0x3b);
619 else
620 /*clear CR91[5] to direct on display period
621 in the secondary diplay path */
622 viafb_write_reg(CR91, VIACR,
623 viafb_read_reg(VIACR, CR91) & 0xDF);
624 }
625
626 if (viaparinfo->chip_info->
627 tmds_chip_info.output_interface == INTERFACE_DVP1) {
628 viafb_write_reg(SR1E, VIASR,
629 viafb_read_reg(VIASR, SR1E) | 0x30);
630
631 /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
632 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
633 tmds_register_write(0x88, 0x3b);
634 } else {
635 /*clear CR91[5] to direct on display period
636 in the secondary diplay path */
637 viafb_write_reg(CR91, VIACR,
638 viafb_read_reg(VIACR, CR91) & 0xDF);
639 }
640
641 /*fix DVI cannot enable on EPIA-M board */
642 if (viafb_platform_epia_dvi == 1) {
643 viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
644 viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
645 if (viafb_bus_width == 24) {
646 if (viafb_device_lcd_dualedge == 1)
647 data = 0x3F;
648 else
649 data = 0x37;
650 viafb_i2c_writebyte(viaparinfo->chip_info->
651 tmds_chip_info.
652 tmds_chip_slave_addr,
653 0x08, data);
654 }
655 }
656 }
657
658 if (viaparinfo->chip_info->
659 tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) {
660 viafb_write_reg(SR2A, VIASR,
661 viafb_read_reg(VIASR, SR2A) | 0x0C);
662 viafb_write_reg(CR91, VIACR,
663 viafb_read_reg(VIACR, CR91) & 0xDF);
664 }
665
666 if (viaparinfo->chip_info->
667 tmds_chip_info.output_interface == INTERFACE_DFP_LOW) {
668 viafb_write_reg(SR2A, VIASR,
669 viafb_read_reg(VIASR, SR2A) | 0x03);
670 viafb_write_reg(CR91, VIACR,
671 viafb_read_reg(VIACR, CR91) & 0xDF);
672 }
673 if (viaparinfo->chip_info->
674 tmds_chip_info.output_interface == INTERFACE_TMDS) {
675 /* Turn on Display period in the panel path. */
676 viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
677
678 /* Turn on TMDS power. */
679 viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
680 }
681}
682
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
new file mode 100644
index 000000000000..e1ec37fb0dc3
--- /dev/null
+++ b/drivers/video/via/dvi.h
@@ -0,0 +1,64 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __DVI_H__
23#define __DVI_H__
24
25/*Definition TMDS Device ID register*/
26#define VT1632_DEVICE_ID_REG 0x02
27#define VT1632_DEVICE_ID 0x92
28
29#define GET_DVI_SIZE_BY_SYSTEM_BIOS 0x01
30#define GET_DVI_SIZE_BY_VGA_BIOS 0x02
31#define GET_DVI_SZIE_BY_HW_STRAPPING 0x03
32
33/* Definition DVI Panel ID*/
34/* Resolution: 640x480, Channel: single, Dithering: Enable */
35#define DVI_PANEL_ID0_640X480 0x00
36/* Resolution: 800x600, Channel: single, Dithering: Enable */
37#define DVI_PANEL_ID1_800x600 0x01
38/* Resolution: 1024x768, Channel: single, Dithering: Enable */
39#define DVI_PANEL_ID1_1024x768 0x02
40/* Resolution: 1280x768, Channel: single, Dithering: Enable */
41#define DVI_PANEL_ID1_1280x768 0x03
42/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
43#define DVI_PANEL_ID1_1280x1024 0x04
44/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
45#define DVI_PANEL_ID1_1400x1050 0x05
46/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
47#define DVI_PANEL_ID1_1600x1200 0x06
48
49/* Define the version of EDID*/
50#define EDID_VERSION_1 1
51#define EDID_VERSION_2 2
52
53#define DEV_CONNECT_DVI 0x01
54#define DEV_CONNECT_HDMI 0x02
55
56struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index);
57int viafb_dvi_sense(void);
58void viafb_dvi_disable(void);
59void viafb_dvi_enable(void);
60int viafb_tmds_trasmitter_identify(void);
61void viafb_init_dvi_size(void);
62void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga);
63
64#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
new file mode 100644
index 000000000000..468be2425af3
--- /dev/null
+++ b/drivers/video/via/global.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include "global.h"
22int viafb_platform_epia_dvi = STATE_OFF;
23int viafb_device_lcd_dualedge = STATE_OFF;
24int viafb_bus_width = 12;
25int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
26int viafb_memsize;
27int viafb_DeviceStatus = CRT_Device;
28int viafb_hotplug;
29int viafb_refresh = 60;
30int viafb_refresh1 = 60;
31int viafb_lcd_dsp_method = LCD_EXPANDSION;
32int viafb_lcd_mode = LCD_OPENLDI;
33int viafb_bpp = 32;
34int viafb_bpp1 = 32;
35int viafb_accel = 1;
36int viafb_CRT_ON = 1;
37int viafb_DVI_ON;
38int viafb_LCD_ON ;
39int viafb_LCD2_ON;
40int viafb_SAMM_ON;
41int viafb_dual_fb;
42int viafb_hotplug_Xres = 640;
43int viafb_hotplug_Yres = 480;
44int viafb_hotplug_bpp = 32;
45int viafb_hotplug_refresh = 60;
46unsigned int viafb_second_offset;
47int viafb_second_size;
48int viafb_primary_dev = None_Device;
49void __iomem *viafb_FB_MM;
50unsigned int viafb_second_xres = 640;
51unsigned int viafb_second_yres = 480;
52unsigned int viafb_second_virtual_xres;
53unsigned int viafb_second_virtual_yres;
54int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
55struct fb_cursor viacursor;
56struct fb_info *viafbinfo;
57struct fb_info *viafbinfo1;
58struct viafb_par *viaparinfo;
59struct viafb_par *viaparinfo1;
60
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
new file mode 100644
index 000000000000..8e5263c5b812
--- /dev/null
+++ b/drivers/video/via/global.h
@@ -0,0 +1,90 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __GLOBAL_H__
23#define __GLOBAL_H__
24
25#include <linux/fb.h>
26#include <linux/delay.h>
27#include <linux/ioport.h>
28#include <linux/pci.h>
29#include <linux/io.h>
30#include <linux/uaccess.h>
31#include <linux/init.h>
32#include <linux/proc_fs.h>
33#include <linux/console.h>
34#include <linux/timer.h>
35
36#include "debug.h"
37
38#include "iface.h"
39#include "viafbdev.h"
40#include "chip.h"
41#include "debug.h"
42#include "accel.h"
43#include "share.h"
44#include "dvi.h"
45#include "viamode.h"
46#include "via_i2c.h"
47#include "hw.h"
48
49#include "lcd.h"
50#include "ioctl.h"
51#include "viamode.h"
52#include "via_utility.h"
53#include "vt1636.h"
54#include "tblDPASetting.h"
55#include "tbl1636.h"
56#include "viafbdev.h"
57
58/* External struct*/
59
60extern int viafb_platform_epia_dvi;
61extern int viafb_device_lcd_dualedge;
62extern int viafb_bus_width;
63extern int viafb_display_hardware_layout;
64extern struct offset offset_reg;
65extern struct viafb_par *viaparinfo;
66extern struct viafb_par *viaparinfo1;
67extern struct fb_info *viafbinfo;
68extern struct fb_info *viafbinfo1;
69extern int viafb_DeviceStatus;
70extern int viafb_refresh;
71extern int viafb_refresh1;
72extern int viafb_lcd_dsp_method;
73extern int viafb_lcd_mode;
74extern int viafb_bpp;
75extern int viafb_bpp1;
76
77extern int viafb_CRT_ON;
78extern int viafb_hotplug_Xres;
79extern int viafb_hotplug_Yres;
80extern int viafb_hotplug_bpp;
81extern int viafb_hotplug_refresh;
82extern int viafb_primary_dev;
83extern void __iomem *viafb_FB_MM;
84extern struct fb_cursor viacursor;
85
86extern unsigned int viafb_second_xres;
87extern unsigned int viafb_second_yres;
88extern int viafb_lcd_panel_id;
89
90#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
new file mode 100644
index 000000000000..fcd53ceb88fa
--- /dev/null
+++ b/drivers/video/via/hw.c
@@ -0,0 +1,2865 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24static const struct pci_device_id_info pciidlist[] = {
25 {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266},
26 {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800},
27 {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400},
28 {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800},
29 {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700},
30 {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890},
31 {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890},
32 {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700},
33 {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900},
34 {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750},
35 {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800},
36 {0, 0, 0}
37};
38
39struct offset offset_reg = {
40 /* IGA1 Offset Register */
41 {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } },
42 /* IGA2 Offset Register */
43 {IGA2_OFFSET_REG_NUM, {{CR66, 0, 7}, {CR67, 0, 1} } }
44};
45
46static struct pll_map pll_value[] = {
47 {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M},
48 {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M},
49 {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M},
50 {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M},
51 {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M},
52 {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M},
53 {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M},
54 {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M},
55 {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M},
56 {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M},
57 {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M},
58 {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M},
59 {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M},
60 {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M},
61 {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M},
62 {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M},
63 {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M},
64 {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M},
65 {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M},
66 {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M},
67 {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M},
68 {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M},
69 {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M},
70 {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M},
71 {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M},
72 {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M},
73 {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M},
74 {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M},
75 {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M},
76 {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M},
77 {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M},
78 {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M},
79 {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M},
80 {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M},
81 {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M},
82 {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M},
83 {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M},
84 {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M},
85 {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M,
86 CX700_101_000M},
87 {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M,
88 CX700_106_500M},
89 {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M,
90 CX700_108_000M},
91 {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M,
92 CX700_113_309M},
93 {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M,
94 CX700_118_840M},
95 {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M,
96 CX700_119_000M},
97 {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M,
98 CX700_121_750M},
99 {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M,
100 CX700_125_104M},
101 {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M,
102 CX700_133_308M},
103 {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M,
104 CX700_135_000M},
105 {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M,
106 CX700_136_700M},
107 {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M,
108 CX700_138_400M},
109 {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M,
110 CX700_146_760M},
111 {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M,
112 CX700_153_920M},
113 {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M,
114 CX700_156_000M},
115 {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M,
116 CX700_157_500M},
117 {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M,
118 CX700_162_000M},
119 {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M,
120 CX700_187_000M},
121 {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M,
122 CX700_193_295M},
123 {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M,
124 CX700_202_500M},
125 {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M,
126 CX700_204_000M},
127 {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M,
128 CX700_218_500M},
129 {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M,
130 CX700_234_000M},
131 {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M,
132 CX700_267_250M},
133 {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M,
134 CX700_297_500M},
135 {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M},
136 {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M,
137 CX700_172_798M},
138 {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M,
139 CX700_122_614M},
140 {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M},
141 {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M,
142 CX700_148_500M}
143};
144
145static struct fifo_depth_select display_fifo_depth_reg = {
146 /* IGA1 FIFO Depth_Select */
147 {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
148 /* IGA2 FIFO Depth_Select */
149 {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
150 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
151};
152
153static struct fifo_threshold_select fifo_threshold_select_reg = {
154 /* IGA1 FIFO Threshold Select */
155 {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
156 /* IGA2 FIFO Threshold Select */
157 {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
158};
159
160static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
161 /* IGA1 FIFO High Threshold Select */
162 {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
163 /* IGA2 FIFO High Threshold Select */
164 {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
165};
166
167static struct display_queue_expire_num display_queue_expire_num_reg = {
168 /* IGA1 Display Queue Expire Num */
169 {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
170 /* IGA2 Display Queue Expire Num */
171 {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
172};
173
174/* Definition Fetch Count Registers*/
175static struct fetch_count fetch_count_reg = {
176 /* IGA1 Fetch Count Register */
177 {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
178 /* IGA2 Fetch Count Register */
179 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
180};
181
182static struct iga1_crtc_timing iga1_crtc_reg = {
183 /* IGA1 Horizontal Total */
184 {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
185 /* IGA1 Horizontal Addressable Video */
186 {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
187 /* IGA1 Horizontal Blank Start */
188 {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
189 /* IGA1 Horizontal Blank End */
190 {IGA1_HOR_BLANK_END_REG_NUM,
191 {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
192 /* IGA1 Horizontal Sync Start */
193 {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
194 /* IGA1 Horizontal Sync End */
195 {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
196 /* IGA1 Vertical Total */
197 {IGA1_VER_TOTAL_REG_NUM,
198 {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
199 /* IGA1 Vertical Addressable Video */
200 {IGA1_VER_ADDR_REG_NUM,
201 {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
202 /* IGA1 Vertical Blank Start */
203 {IGA1_VER_BLANK_START_REG_NUM,
204 {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
205 /* IGA1 Vertical Blank End */
206 {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
207 /* IGA1 Vertical Sync Start */
208 {IGA1_VER_SYNC_START_REG_NUM,
209 {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
210 /* IGA1 Vertical Sync End */
211 {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
212};
213
214static struct iga2_crtc_timing iga2_crtc_reg = {
215 /* IGA2 Horizontal Total */
216 {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
217 /* IGA2 Horizontal Addressable Video */
218 {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
219 /* IGA2 Horizontal Blank Start */
220 {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
221 /* IGA2 Horizontal Blank End */
222 {IGA2_HOR_BLANK_END_REG_NUM,
223 {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
224 /* IGA2 Horizontal Sync Start */
225 {IGA2_HOR_SYNC_START_REG_NUM,
226 {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
227 /* IGA2 Horizontal Sync End */
228 {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
229 /* IGA2 Vertical Total */
230 {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
231 /* IGA2 Vertical Addressable Video */
232 {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
233 /* IGA2 Vertical Blank Start */
234 {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
235 /* IGA2 Vertical Blank End */
236 {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
237 /* IGA2 Vertical Sync Start */
238 {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
239 /* IGA2 Vertical Sync End */
240 {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
241};
242
243static struct rgbLUT palLUT_table[] = {
244 /* {R,G,B} */
245 /* Index 0x00~0x03 */
246 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
247 0x2A,
248 0x2A},
249 /* Index 0x04~0x07 */
250 {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
251 0x2A,
252 0x2A},
253 /* Index 0x08~0x0B */
254 {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
255 0x3F,
256 0x3F},
257 /* Index 0x0C~0x0F */
258 {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
259 0x3F,
260 0x3F},
261 /* Index 0x10~0x13 */
262 {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
263 0x0B,
264 0x0B},
265 /* Index 0x14~0x17 */
266 {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
267 0x18,
268 0x18},
269 /* Index 0x18~0x1B */
270 {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
271 0x28,
272 0x28},
273 /* Index 0x1C~0x1F */
274 {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
275 0x3F,
276 0x3F},
277 /* Index 0x20~0x23 */
278 {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
279 0x00,
280 0x3F},
281 /* Index 0x24~0x27 */
282 {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
283 0x00,
284 0x10},
285 /* Index 0x28~0x2B */
286 {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
287 0x2F,
288 0x00},
289 /* Index 0x2C~0x2F */
290 {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
291 0x3F,
292 0x00},
293 /* Index 0x30~0x33 */
294 {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
295 0x3F,
296 0x2F},
297 /* Index 0x34~0x37 */
298 {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
299 0x10,
300 0x3F},
301 /* Index 0x38~0x3B */
302 {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
303 0x1F,
304 0x3F},
305 /* Index 0x3C~0x3F */
306 {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
307 0x1F,
308 0x27},
309 /* Index 0x40~0x43 */
310 {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
311 0x3F,
312 0x1F},
313 /* Index 0x44~0x47 */
314 {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
315 0x3F,
316 0x1F},
317 /* Index 0x48~0x4B */
318 {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
319 0x3F,
320 0x37},
321 /* Index 0x4C~0x4F */
322 {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
323 0x27,
324 0x3F},
325 /* Index 0x50~0x53 */
326 {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
327 0x2D,
328 0x3F},
329 /* Index 0x54~0x57 */
330 {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
331 0x2D,
332 0x31},
333 /* Index 0x58~0x5B */
334 {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
335 0x3A,
336 0x2D},
337 /* Index 0x5C~0x5F */
338 {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
339 0x3F,
340 0x2D},
341 /* Index 0x60~0x63 */
342 {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
343 0x3F,
344 0x3A},
345 /* Index 0x64~0x67 */
346 {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
347 0x31,
348 0x3F},
349 /* Index 0x68~0x6B */
350 {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
351 0x00,
352 0x1C},
353 /* Index 0x6C~0x6F */
354 {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
355 0x00,
356 0x07},
357 /* Index 0x70~0x73 */
358 {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
359 0x15,
360 0x00},
361 /* Index 0x74~0x77 */
362 {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
363 0x1C,
364 0x00},
365 /* Index 0x78~0x7B */
366 {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
367 0x1C,
368 0x15},
369 /* Index 0x7C~0x7F */
370 {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
371 0x07,
372 0x1C},
373 /* Index 0x80~0x83 */
374 {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
375 0x0E,
376 0x1C},
377 /* Index 0x84~0x87 */
378 {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
379 0x0E,
380 0x11},
381 /* Index 0x88~0x8B */
382 {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
383 0x18,
384 0x0E},
385 /* Index 0x8C~0x8F */
386 {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
387 0x1C,
388 0x0E},
389 /* Index 0x90~0x93 */
390 {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
391 0x1C,
392 0x18},
393 /* Index 0x94~0x97 */
394 {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
395 0x11,
396 0x1C},
397 /* Index 0x98~0x9B */
398 {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
399 0x14,
400 0x1C},
401 /* Index 0x9C~0x9F */
402 {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
403 0x14,
404 0x16},
405 /* Index 0xA0~0xA3 */
406 {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
407 0x1A,
408 0x14},
409 /* Index 0xA4~0xA7 */
410 {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
411 0x1C,
412 0x14},
413 /* Index 0xA8~0xAB */
414 {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
415 0x1C,
416 0x1A},
417 /* Index 0xAC~0xAF */
418 {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
419 0x16,
420 0x1C},
421 /* Index 0xB0~0xB3 */
422 {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
423 0x00,
424 0x10},
425 /* Index 0xB4~0xB7 */
426 {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
427 0x00,
428 0x04},
429 /* Index 0xB8~0xBB */
430 {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
431 0x0C,
432 0x00},
433 /* Index 0xBC~0xBF */
434 {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
435 0x10,
436 0x00},
437 /* Index 0xC0~0xC3 */
438 {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
439 0x10,
440 0x0C},
441 /* Index 0xC4~0xC7 */
442 {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
443 0x04,
444 0x10},
445 /* Index 0xC8~0xCB */
446 {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
447 0x08,
448 0x10},
449 /* Index 0xCC~0xCF */
450 {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
451 0x08,
452 0x0A},
453 /* Index 0xD0~0xD3 */
454 {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
455 0x0E,
456 0x08},
457 /* Index 0xD4~0xD7 */
458 {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
459 0x10,
460 0x08},
461 /* Index 0xD8~0xDB */
462 {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
463 0x10,
464 0x0E},
465 /* Index 0xDC~0xDF */
466 {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
467 0x0A,
468 0x10},
469 /* Index 0xE0~0xE3 */
470 {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
471 0x0B,
472 0x10},
473 /* Index 0xE4~0xE7 */
474 {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
475 0x0B,
476 0x0C},
477 /* Index 0xE8~0xEB */
478 {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
479 0x0F,
480 0x0B},
481 /* Index 0xEC~0xEF */
482 {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
483 0x10,
484 0x0B},
485 /* Index 0xF0~0xF3 */
486 {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
487 0x10,
488 0x0F},
489 /* Index 0xF4~0xF7 */
490 {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
491 0x0C,
492 0x10},
493 /* Index 0xF8~0xFB */
494 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
495 0x00,
496 0x00},
497 /* Index 0xFC~0xFF */
498 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
499 0x00,
500 0x00}
501};
502
503static void set_crt_output_path(int set_iga);
504static void dvi_patch_skew_dvp0(void);
505static void dvi_patch_skew_dvp1(void);
506static void dvi_patch_skew_dvp_low(void);
507static void set_dvi_output_path(int set_iga, int output_interface);
508static void set_lcd_output_path(int set_iga, int output_interface);
509static int search_mode_setting(int ModeInfoIndex);
510static void load_fix_bit_crtc_reg(void);
511static void init_gfx_chip_info(void);
512static void init_tmds_chip_info(void);
513static void init_lvds_chip_info(void);
514static void device_screen_off(void);
515static void device_screen_on(void);
516static void set_display_channel(void);
517static void device_off(void);
518static void device_on(void);
519static void enable_second_display_channel(void);
520static void disable_second_display_channel(void);
521static int get_fb_size_from_pci(void);
522
523void viafb_write_reg(u8 index, u16 io_port, u8 data)
524{
525 outb(index, io_port);
526 outb(data, io_port + 1);
527 /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */
528}
529u8 viafb_read_reg(int io_port, u8 index)
530{
531 outb(index, io_port);
532 return inb(io_port + 1);
533}
534
535void viafb_lock_crt(void)
536{
537 viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
538}
539
540void viafb_unlock_crt(void)
541{
542 viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
543 viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
544}
545
546void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask)
547{
548 u8 tmp;
549
550 outb(index, io_port);
551 tmp = inb(io_port + 1);
552 outb((data & mask) | (tmp & (~mask)), io_port + 1);
553 /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */
554}
555
556void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
557{
558 outb(index, LUT_INDEX_WRITE);
559 outb(r, LUT_DATA);
560 outb(g, LUT_DATA);
561 outb(b, LUT_DATA);
562}
563
564/*Set IGA path for each device*/
565void viafb_set_iga_path(void)
566{
567
568 if (viafb_SAMM_ON == 1) {
569 if (viafb_CRT_ON) {
570 if (viafb_primary_dev == CRT_Device)
571 viaparinfo->crt_setting_info->iga_path = IGA1;
572 else
573 viaparinfo->crt_setting_info->iga_path = IGA2;
574 }
575
576 if (viafb_DVI_ON) {
577 if (viafb_primary_dev == DVI_Device)
578 viaparinfo->tmds_setting_info->iga_path = IGA1;
579 else
580 viaparinfo->tmds_setting_info->iga_path = IGA2;
581 }
582
583 if (viafb_LCD_ON) {
584 if (viafb_primary_dev == LCD_Device) {
585 if (viafb_dual_fb &&
586 (viaparinfo->chip_info->gfx_chip_name ==
587 UNICHROME_CLE266)) {
588 viaparinfo->
589 lvds_setting_info->iga_path = IGA2;
590 viaparinfo->
591 crt_setting_info->iga_path = IGA1;
592 viaparinfo->
593 tmds_setting_info->iga_path = IGA1;
594 } else
595 viaparinfo->
596 lvds_setting_info->iga_path = IGA1;
597 } else {
598 viaparinfo->lvds_setting_info->iga_path = IGA2;
599 }
600 }
601 if (viafb_LCD2_ON) {
602 if (LCD2_Device == viafb_primary_dev)
603 viaparinfo->lvds_setting_info2->iga_path = IGA1;
604 else
605 viaparinfo->lvds_setting_info2->iga_path = IGA2;
606 }
607 } else {
608 viafb_SAMM_ON = 0;
609
610 if (viafb_CRT_ON && viafb_LCD_ON) {
611 viaparinfo->crt_setting_info->iga_path = IGA1;
612 viaparinfo->lvds_setting_info->iga_path = IGA2;
613 } else if (viafb_CRT_ON && viafb_DVI_ON) {
614 viaparinfo->crt_setting_info->iga_path = IGA1;
615 viaparinfo->tmds_setting_info->iga_path = IGA2;
616 } else if (viafb_LCD_ON && viafb_DVI_ON) {
617 viaparinfo->tmds_setting_info->iga_path = IGA1;
618 viaparinfo->lvds_setting_info->iga_path = IGA2;
619 } else if (viafb_LCD_ON && viafb_LCD2_ON) {
620 viaparinfo->lvds_setting_info->iga_path = IGA2;
621 viaparinfo->lvds_setting_info2->iga_path = IGA2;
622 } else if (viafb_CRT_ON) {
623 viaparinfo->crt_setting_info->iga_path = IGA1;
624 } else if (viafb_LCD_ON) {
625 viaparinfo->lvds_setting_info->iga_path = IGA2;
626 } else if (viafb_DVI_ON) {
627 viaparinfo->tmds_setting_info->iga_path = IGA1;
628 }
629 }
630}
631
632void viafb_set_start_addr(void)
633{
634 unsigned long offset = 0, tmp = 0, size = 0;
635 unsigned long length;
636
637 DEBUG_MSG(KERN_INFO "viafb_set_start_addr!\n");
638 viafb_unlock_crt();
639 /* update starting address of IGA1 */
640 viafb_write_reg(CR0C, VIACR, 0x00); /*initial starting address */
641 viafb_write_reg(CR0D, VIACR, 0x00);
642 viafb_write_reg(CR34, VIACR, 0x00);
643 viafb_write_reg_mask(CR48, VIACR, 0x00, 0x1F);
644
645 if (viafb_dual_fb) {
646 viaparinfo->iga_path = IGA1;
647 viaparinfo1->iga_path = IGA2;
648 }
649
650 if (viafb_SAMM_ON == 1) {
651 if (!viafb_dual_fb) {
652 if (viafb_second_size)
653 size = viafb_second_size * 1024 * 1024;
654 else
655 size = 8 * 1024 * 1024;
656 } else {
657
658 size = viaparinfo1->memsize;
659 }
660 offset = viafb_second_offset;
661 DEBUG_MSG(KERN_INFO
662 "viafb_second_size=%lx, second start_adddress=%lx\n",
663 size, offset);
664 }
665 if (viafb_SAMM_ON == 1) {
666 offset = offset >> 3;
667
668 tmp = viafb_read_reg(VIACR, 0x62) & 0x01;
669 tmp |= (offset & 0x7F) << 1;
670 viafb_write_reg(CR62, VIACR, tmp);
671 viafb_write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7));
672 viafb_write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15));
673 viafb_write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23));
674 } else {
675 /* update starting address */
676 viafb_write_reg(CR62, VIACR, 0x00);
677 viafb_write_reg(CR63, VIACR, 0x00);
678 viafb_write_reg(CR64, VIACR, 0x00);
679 viafb_write_reg(CRA3, VIACR, 0x00);
680 }
681
682 if (viafb_SAMM_ON == 1) {
683 if (viafb_accel) {
684 if (!viafb_dual_fb)
685 length = size - viaparinfo->fbmem_used;
686 else
687 length = size - viaparinfo1->fbmem_used;
688 } else
689 length = size;
690 offset = (unsigned long)(void *)viafb_FB_MM +
691 viafb_second_offset;
692 memset((void *)offset, 0, length);
693 }
694
695 viafb_lock_crt();
696}
697
698void viafb_set_output_path(int device, int set_iga, int output_interface)
699{
700 switch (device) {
701 case DEVICE_CRT:
702 set_crt_output_path(set_iga);
703 break;
704 case DEVICE_DVI:
705 set_dvi_output_path(set_iga, output_interface);
706 break;
707 case DEVICE_LCD:
708 set_lcd_output_path(set_iga, output_interface);
709 break;
710 }
711}
712
713static void set_crt_output_path(int set_iga)
714{
715 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
716
717 switch (set_iga) {
718 case IGA1:
719 viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6);
720 break;
721 case IGA2:
722 case IGA1_IGA2:
723 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
724 viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
725 if (set_iga == IGA1_IGA2)
726 viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
727 break;
728 }
729}
730
731static void dvi_patch_skew_dvp0(void)
732{
733 /* Reset data driving first: */
734 viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
735 viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
736
737 switch (viaparinfo->chip_info->gfx_chip_name) {
738 case UNICHROME_P4M890:
739 {
740 if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
741 (viaparinfo->tmds_setting_info->v_active ==
742 1200))
743 viafb_write_reg_mask(CR96, VIACR, 0x03,
744 BIT0 + BIT1 + BIT2);
745 else
746 viafb_write_reg_mask(CR96, VIACR, 0x07,
747 BIT0 + BIT1 + BIT2);
748 break;
749 }
750
751 case UNICHROME_P4M900:
752 {
753 viafb_write_reg_mask(CR96, VIACR, 0x07,
754 BIT0 + BIT1 + BIT2 + BIT3);
755 viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
756 viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
757 break;
758 }
759
760 default:
761 {
762 break;
763 }
764 }
765}
766
767static void dvi_patch_skew_dvp1(void)
768{
769 switch (viaparinfo->chip_info->gfx_chip_name) {
770 case UNICHROME_CX700:
771 {
772 break;
773 }
774
775 default:
776 {
777 break;
778 }
779 }
780}
781
782static void dvi_patch_skew_dvp_low(void)
783{
784 switch (viaparinfo->chip_info->gfx_chip_name) {
785 case UNICHROME_K8M890:
786 {
787 viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
788 break;
789 }
790
791 case UNICHROME_P4M900:
792 {
793 viafb_write_reg_mask(CR99, VIACR, 0x08,
794 BIT0 + BIT1 + BIT2 + BIT3);
795 break;
796 }
797
798 case UNICHROME_P4M890:
799 {
800 viafb_write_reg_mask(CR99, VIACR, 0x0F,
801 BIT0 + BIT1 + BIT2 + BIT3);
802 break;
803 }
804
805 default:
806 {
807 break;
808 }
809 }
810}
811
812static void set_dvi_output_path(int set_iga, int output_interface)
813{
814 switch (output_interface) {
815 case INTERFACE_DVP0:
816 viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
817
818 if (set_iga == IGA1) {
819 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
820 viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 +
821 BIT5 + BIT7);
822 } else {
823 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
824 viafb_write_reg_mask(CR6C, VIACR, 0xA1, BIT0 +
825 BIT5 + BIT7);
826 }
827
828 viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
829
830 dvi_patch_skew_dvp0();
831 break;
832
833 case INTERFACE_DVP1:
834 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
835 if (set_iga == IGA1)
836 viafb_write_reg_mask(CR93, VIACR, 0x21,
837 BIT0 + BIT5 + BIT7);
838 else
839 viafb_write_reg_mask(CR93, VIACR, 0xA1,
840 BIT0 + BIT5 + BIT7);
841 } else {
842 if (set_iga == IGA1)
843 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
844 else
845 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
846 }
847
848 viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
849 dvi_patch_skew_dvp1();
850 break;
851 case INTERFACE_DFP_HIGH:
852 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) {
853 if (set_iga == IGA1) {
854 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
855 viafb_write_reg_mask(CR97, VIACR, 0x03,
856 BIT0 + BIT1 + BIT4);
857 } else {
858 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
859 viafb_write_reg_mask(CR97, VIACR, 0x13,
860 BIT0 + BIT1 + BIT4);
861 }
862 }
863 viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
864 break;
865
866 case INTERFACE_DFP_LOW:
867 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
868 break;
869
870 if (set_iga == IGA1) {
871 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
872 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
873 } else {
874 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
875 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
876 }
877
878 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
879 dvi_patch_skew_dvp_low();
880 break;
881
882 case INTERFACE_TMDS:
883 if (set_iga == IGA1)
884 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
885 else
886 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
887 break;
888 }
889
890 if (set_iga == IGA2) {
891 enable_second_display_channel();
892 /* Disable LCD Scaling */
893 viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
894 }
895}
896
897static void set_lcd_output_path(int set_iga, int output_interface)
898{
899 DEBUG_MSG(KERN_INFO
900 "set_lcd_output_path, iga:%d,out_interface:%d\n",
901 set_iga, output_interface);
902 switch (set_iga) {
903 case IGA1:
904 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
905 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
906
907 disable_second_display_channel();
908 break;
909
910 case IGA2:
911 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
912 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
913
914 enable_second_display_channel();
915 break;
916
917 case IGA1_IGA2:
918 viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
919 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
920
921 disable_second_display_channel();
922 break;
923 }
924
925 switch (output_interface) {
926 case INTERFACE_DVP0:
927 if (set_iga == IGA1) {
928 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
929 } else {
930 viafb_write_reg(CR91, VIACR, 0x00);
931 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
932 }
933 break;
934
935 case INTERFACE_DVP1:
936 if (set_iga == IGA1)
937 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
938 else {
939 viafb_write_reg(CR91, VIACR, 0x00);
940 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
941 }
942 break;
943
944 case INTERFACE_DFP_HIGH:
945 if (set_iga == IGA1)
946 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
947 else {
948 viafb_write_reg(CR91, VIACR, 0x00);
949 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
950 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
951 }
952 break;
953
954 case INTERFACE_DFP_LOW:
955 if (set_iga == IGA1)
956 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
957 else {
958 viafb_write_reg(CR91, VIACR, 0x00);
959 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
960 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
961 }
962
963 break;
964
965 case INTERFACE_DFP:
966 if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
967 || (UNICHROME_P4M890 ==
968 viaparinfo->chip_info->gfx_chip_name))
969 viafb_write_reg_mask(CR97, VIACR, 0x84,
970 BIT7 + BIT2 + BIT1 + BIT0);
971 if (set_iga == IGA1) {
972 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
973 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
974 } else {
975 viafb_write_reg(CR91, VIACR, 0x00);
976 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
977 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
978 }
979 break;
980
981 case INTERFACE_LVDS0:
982 case INTERFACE_LVDS0LVDS1:
983 if (set_iga == IGA1)
984 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
985 else
986 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
987
988 break;
989
990 case INTERFACE_LVDS1:
991 if (set_iga == IGA1)
992 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
993 else
994 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
995 break;
996 }
997}
998
999/* Search Mode Index */
1000static int search_mode_setting(int ModeInfoIndex)
1001{
1002 int i = 0;
1003
1004 while ((i < NUM_TOTAL_MODETABLE) &&
1005 (ModeInfoIndex != CLE266Modes[i].ModeIndex))
1006 i++;
1007 if (i >= NUM_TOTAL_MODETABLE)
1008 i = 0;
1009 return i;
1010
1011}
1012
1013struct VideoModeTable *viafb_get_modetbl_pointer(int Index)
1014{
1015 struct VideoModeTable *TmpTbl = NULL;
1016 TmpTbl = &CLE266Modes[search_mode_setting(Index)];
1017 return TmpTbl;
1018}
1019
1020struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index)
1021{
1022 struct VideoModeTable *TmpTbl = NULL;
1023 int i = 0;
1024 while ((i < NUM_TOTAL_CEA_MODES) &&
1025 (Index != CEA_HDMI_Modes[i].ModeIndex))
1026 i++;
1027 if ((i < NUM_TOTAL_CEA_MODES))
1028 TmpTbl = &CEA_HDMI_Modes[i];
1029 else {
1030 /*Still use general timing if don't find CEA timing */
1031 i = 0;
1032 while ((i < NUM_TOTAL_MODETABLE) &&
1033 (Index != CLE266Modes[i].ModeIndex))
1034 i++;
1035 if (i >= NUM_TOTAL_MODETABLE)
1036 i = 0;
1037 TmpTbl = &CLE266Modes[i];
1038 }
1039 return TmpTbl;
1040}
1041
1042static void load_fix_bit_crtc_reg(void)
1043{
1044 /* always set to 1 */
1045 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
1046 /* line compare should set all bits = 1 (extend modes) */
1047 viafb_write_reg(CR18, VIACR, 0xff);
1048 /* line compare should set all bits = 1 (extend modes) */
1049 viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4);
1050 /* line compare should set all bits = 1 (extend modes) */
1051 viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6);
1052 /* line compare should set all bits = 1 (extend modes) */
1053 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
1054 /* line compare should set all bits = 1 (extend modes) */
1055 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
1056 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
1057 /* extend mode always set to e3h */
1058 viafb_write_reg(CR17, VIACR, 0xe3);
1059 /* extend mode always set to 0h */
1060 viafb_write_reg(CR08, VIACR, 0x00);
1061 /* extend mode always set to 0h */
1062 viafb_write_reg(CR14, VIACR, 0x00);
1063
1064 /* If K8M800, enable Prefetch Mode. */
1065 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
1066 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
1067 viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
1068 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
1069 && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
1070 viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
1071
1072}
1073
1074void viafb_load_reg(int timing_value, int viafb_load_reg_num,
1075 struct io_register *reg,
1076 int io_type)
1077{
1078 int reg_mask;
1079 int bit_num = 0;
1080 int data;
1081 int i, j;
1082 int shift_next_reg;
1083 int start_index, end_index, cr_index;
1084 u16 get_bit;
1085
1086 for (i = 0; i < viafb_load_reg_num; i++) {
1087 reg_mask = 0;
1088 data = 0;
1089 start_index = reg[i].start_bit;
1090 end_index = reg[i].end_bit;
1091 cr_index = reg[i].io_addr;
1092
1093 shift_next_reg = bit_num;
1094 for (j = start_index; j <= end_index; j++) {
1095 /*if (bit_num==8) timing_value = timing_value >>8; */
1096 reg_mask = reg_mask | (BIT0 << j);
1097 get_bit = (timing_value & (BIT0 << bit_num));
1098 data =
1099 data | ((get_bit >> shift_next_reg) << start_index);
1100 bit_num++;
1101 }
1102 if (io_type == VIACR)
1103 viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
1104 else
1105 viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
1106 }
1107
1108}
1109
1110/* Write Registers */
1111void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1112{
1113 int i;
1114 unsigned char RegTemp;
1115
1116 /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
1117
1118 for (i = 0; i < ItemNum; i++) {
1119 outb(RegTable[i].index, RegTable[i].port);
1120 RegTemp = inb(RegTable[i].port + 1);
1121 RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value;
1122 outb(RegTemp, RegTable[i].port + 1);
1123 }
1124}
1125
1126void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga)
1127{
1128 int reg_value;
1129 int viafb_load_reg_num;
1130 struct io_register *reg;
1131
1132 switch (set_iga) {
1133 case IGA1_IGA2:
1134 case IGA1:
1135 reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte);
1136 viafb_load_reg_num = offset_reg.iga1_offset_reg.reg_num;
1137 reg = offset_reg.iga1_offset_reg.reg;
1138 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1139 if (set_iga == IGA1)
1140 break;
1141 case IGA2:
1142 reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte);
1143 viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
1144 reg = offset_reg.iga2_offset_reg.reg;
1145 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1146 break;
1147 }
1148}
1149
1150void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1151{
1152 int reg_value;
1153 int viafb_load_reg_num;
1154 struct io_register *reg = NULL;
1155
1156 switch (set_iga) {
1157 case IGA1_IGA2:
1158 case IGA1:
1159 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1160 viafb_load_reg_num = fetch_count_reg.
1161 iga1_fetch_count_reg.reg_num;
1162 reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1163 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1164 if (set_iga == IGA1)
1165 break;
1166 case IGA2:
1167 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1168 viafb_load_reg_num = fetch_count_reg.
1169 iga2_fetch_count_reg.reg_num;
1170 reg = fetch_count_reg.iga2_fetch_count_reg.reg;
1171 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1172 break;
1173 }
1174
1175}
1176
1177void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1178{
1179 int reg_value;
1180 int viafb_load_reg_num;
1181 struct io_register *reg = NULL;
1182 int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
1183 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
1184 int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
1185 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
1186
1187 if (set_iga == IGA1) {
1188 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1189 iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
1190 iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
1191 iga1_fifo_high_threshold =
1192 K800_IGA1_FIFO_HIGH_THRESHOLD;
1193 /* If resolution > 1280x1024, expire length = 64, else
1194 expire length = 128 */
1195 if ((hor_active > 1280) && (ver_active > 1024))
1196 iga1_display_queue_expire_num = 16;
1197 else
1198 iga1_display_queue_expire_num =
1199 K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1200
1201 }
1202
1203 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1204 iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
1205 iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
1206 iga1_fifo_high_threshold =
1207 P880_IGA1_FIFO_HIGH_THRESHOLD;
1208 iga1_display_queue_expire_num =
1209 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1210
1211 /* If resolution > 1280x1024, expire length = 64, else
1212 expire length = 128 */
1213 if ((hor_active > 1280) && (ver_active > 1024))
1214 iga1_display_queue_expire_num = 16;
1215 else
1216 iga1_display_queue_expire_num =
1217 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1218 }
1219
1220 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1221 iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
1222 iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
1223 iga1_fifo_high_threshold =
1224 CN700_IGA1_FIFO_HIGH_THRESHOLD;
1225
1226 /* If resolution > 1280x1024, expire length = 64,
1227 else expire length = 128 */
1228 if ((hor_active > 1280) && (ver_active > 1024))
1229 iga1_display_queue_expire_num = 16;
1230 else
1231 iga1_display_queue_expire_num =
1232 CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1233 }
1234
1235 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1236 iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
1237 iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
1238 iga1_fifo_high_threshold =
1239 CX700_IGA1_FIFO_HIGH_THRESHOLD;
1240 iga1_display_queue_expire_num =
1241 CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1242 }
1243
1244 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1245 iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
1246 iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
1247 iga1_fifo_high_threshold =
1248 K8M890_IGA1_FIFO_HIGH_THRESHOLD;
1249 iga1_display_queue_expire_num =
1250 K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1251 }
1252
1253 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1254 iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
1255 iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
1256 iga1_fifo_high_threshold =
1257 P4M890_IGA1_FIFO_HIGH_THRESHOLD;
1258 iga1_display_queue_expire_num =
1259 P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1260 }
1261
1262 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1263 iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
1264 iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
1265 iga1_fifo_high_threshold =
1266 P4M900_IGA1_FIFO_HIGH_THRESHOLD;
1267 iga1_display_queue_expire_num =
1268 P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1269 }
1270
1271 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1272 iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
1273 iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
1274 iga1_fifo_high_threshold =
1275 VX800_IGA1_FIFO_HIGH_THRESHOLD;
1276 iga1_display_queue_expire_num =
1277 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1278 }
1279
1280 /* Set Display FIFO Depath Select */
1281 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1282 viafb_load_reg_num =
1283 display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
1284 reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
1285 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1286
1287 /* Set Display FIFO Threshold Select */
1288 reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
1289 viafb_load_reg_num =
1290 fifo_threshold_select_reg.
1291 iga1_fifo_threshold_select_reg.reg_num;
1292 reg =
1293 fifo_threshold_select_reg.
1294 iga1_fifo_threshold_select_reg.reg;
1295 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1296
1297 /* Set FIFO High Threshold Select */
1298 reg_value =
1299 IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
1300 viafb_load_reg_num =
1301 fifo_high_threshold_select_reg.
1302 iga1_fifo_high_threshold_select_reg.reg_num;
1303 reg =
1304 fifo_high_threshold_select_reg.
1305 iga1_fifo_high_threshold_select_reg.reg;
1306 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1307
1308 /* Set Display Queue Expire Num */
1309 reg_value =
1310 IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1311 (iga1_display_queue_expire_num);
1312 viafb_load_reg_num =
1313 display_queue_expire_num_reg.
1314 iga1_display_queue_expire_num_reg.reg_num;
1315 reg =
1316 display_queue_expire_num_reg.
1317 iga1_display_queue_expire_num_reg.reg;
1318 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1319
1320 } else {
1321 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1322 iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
1323 iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
1324 iga2_fifo_high_threshold =
1325 K800_IGA2_FIFO_HIGH_THRESHOLD;
1326
1327 /* If resolution > 1280x1024, expire length = 64,
1328 else expire length = 128 */
1329 if ((hor_active > 1280) && (ver_active > 1024))
1330 iga2_display_queue_expire_num = 16;
1331 else
1332 iga2_display_queue_expire_num =
1333 K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1334 }
1335
1336 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1337 iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
1338 iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
1339 iga2_fifo_high_threshold =
1340 P880_IGA2_FIFO_HIGH_THRESHOLD;
1341
1342 /* If resolution > 1280x1024, expire length = 64,
1343 else expire length = 128 */
1344 if ((hor_active > 1280) && (ver_active > 1024))
1345 iga2_display_queue_expire_num = 16;
1346 else
1347 iga2_display_queue_expire_num =
1348 P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1349 }
1350
1351 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1352 iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
1353 iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
1354 iga2_fifo_high_threshold =
1355 CN700_IGA2_FIFO_HIGH_THRESHOLD;
1356
1357 /* If resolution > 1280x1024, expire length = 64,
1358 else expire length = 128 */
1359 if ((hor_active > 1280) && (ver_active > 1024))
1360 iga2_display_queue_expire_num = 16;
1361 else
1362 iga2_display_queue_expire_num =
1363 CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1364 }
1365
1366 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1367 iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
1368 iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
1369 iga2_fifo_high_threshold =
1370 CX700_IGA2_FIFO_HIGH_THRESHOLD;
1371 iga2_display_queue_expire_num =
1372 CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1373 }
1374
1375 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1376 iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
1377 iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
1378 iga2_fifo_high_threshold =
1379 K8M890_IGA2_FIFO_HIGH_THRESHOLD;
1380 iga2_display_queue_expire_num =
1381 K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1382 }
1383
1384 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1385 iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
1386 iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
1387 iga2_fifo_high_threshold =
1388 P4M890_IGA2_FIFO_HIGH_THRESHOLD;
1389 iga2_display_queue_expire_num =
1390 P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1391 }
1392
1393 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1394 iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
1395 iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
1396 iga2_fifo_high_threshold =
1397 P4M900_IGA2_FIFO_HIGH_THRESHOLD;
1398 iga2_display_queue_expire_num =
1399 P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1400 }
1401
1402 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1403 iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
1404 iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
1405 iga2_fifo_high_threshold =
1406 VX800_IGA2_FIFO_HIGH_THRESHOLD;
1407 iga2_display_queue_expire_num =
1408 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1409 }
1410
1411 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1412 /* Set Display FIFO Depath Select */
1413 reg_value =
1414 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
1415 - 1;
1416 /* Patch LCD in IGA2 case */
1417 viafb_load_reg_num =
1418 display_fifo_depth_reg.
1419 iga2_fifo_depth_select_reg.reg_num;
1420 reg =
1421 display_fifo_depth_reg.
1422 iga2_fifo_depth_select_reg.reg;
1423 viafb_load_reg(reg_value,
1424 viafb_load_reg_num, reg, VIACR);
1425 } else {
1426
1427 /* Set Display FIFO Depath Select */
1428 reg_value =
1429 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
1430 viafb_load_reg_num =
1431 display_fifo_depth_reg.
1432 iga2_fifo_depth_select_reg.reg_num;
1433 reg =
1434 display_fifo_depth_reg.
1435 iga2_fifo_depth_select_reg.reg;
1436 viafb_load_reg(reg_value,
1437 viafb_load_reg_num, reg, VIACR);
1438 }
1439
1440 /* Set Display FIFO Threshold Select */
1441 reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
1442 viafb_load_reg_num =
1443 fifo_threshold_select_reg.
1444 iga2_fifo_threshold_select_reg.reg_num;
1445 reg =
1446 fifo_threshold_select_reg.
1447 iga2_fifo_threshold_select_reg.reg;
1448 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1449
1450 /* Set FIFO High Threshold Select */
1451 reg_value =
1452 IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
1453 viafb_load_reg_num =
1454 fifo_high_threshold_select_reg.
1455 iga2_fifo_high_threshold_select_reg.reg_num;
1456 reg =
1457 fifo_high_threshold_select_reg.
1458 iga2_fifo_high_threshold_select_reg.reg;
1459 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1460
1461 /* Set Display Queue Expire Num */
1462 reg_value =
1463 IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1464 (iga2_display_queue_expire_num);
1465 viafb_load_reg_num =
1466 display_queue_expire_num_reg.
1467 iga2_display_queue_expire_num_reg.reg_num;
1468 reg =
1469 display_queue_expire_num_reg.
1470 iga2_display_queue_expire_num_reg.reg;
1471 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1472
1473 }
1474
1475}
1476
1477u32 viafb_get_clk_value(int clk)
1478{
1479 int i;
1480
1481 for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) {
1482 if (clk == pll_value[i].clk) {
1483 switch (viaparinfo->chip_info->gfx_chip_name) {
1484 case UNICHROME_CLE266:
1485 case UNICHROME_K400:
1486 return pll_value[i].cle266_pll;
1487
1488 case UNICHROME_K800:
1489 case UNICHROME_PM800:
1490 case UNICHROME_CN700:
1491 return pll_value[i].k800_pll;
1492
1493 case UNICHROME_CX700:
1494 case UNICHROME_K8M890:
1495 case UNICHROME_P4M890:
1496 case UNICHROME_P4M900:
1497 case UNICHROME_VX800:
1498 return pll_value[i].cx700_pll;
1499 }
1500 }
1501 }
1502
1503 DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n");
1504 return 0;
1505}
1506
1507/* Set VCLK*/
1508void viafb_set_vclock(u32 CLK, int set_iga)
1509{
1510 unsigned char RegTemp;
1511
1512 /* H.W. Reset : ON */
1513 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1514
1515 if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
1516 /* Change D,N FOR VCLK */
1517 switch (viaparinfo->chip_info->gfx_chip_name) {
1518 case UNICHROME_CLE266:
1519 case UNICHROME_K400:
1520 viafb_write_reg(SR46, VIASR, CLK / 0x100);
1521 viafb_write_reg(SR47, VIASR, CLK % 0x100);
1522 break;
1523
1524 case UNICHROME_K800:
1525 case UNICHROME_PM800:
1526 case UNICHROME_CN700:
1527 case UNICHROME_CX700:
1528 case UNICHROME_K8M890:
1529 case UNICHROME_P4M890:
1530 case UNICHROME_P4M900:
1531 case UNICHROME_VX800:
1532 viafb_write_reg(SR44, VIASR, CLK / 0x10000);
1533 DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000);
1534 viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100);
1535 DEBUG_MSG(KERN_INFO "\nSR45=%x",
1536 (CLK & 0xFFFF) / 0x100);
1537 viafb_write_reg(SR46, VIASR, CLK % 0x100);
1538 DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100);
1539 break;
1540 }
1541 }
1542
1543 if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
1544 /* Change D,N FOR LCK */
1545 switch (viaparinfo->chip_info->gfx_chip_name) {
1546 case UNICHROME_CLE266:
1547 case UNICHROME_K400:
1548 viafb_write_reg(SR44, VIASR, CLK / 0x100);
1549 viafb_write_reg(SR45, VIASR, CLK % 0x100);
1550 break;
1551
1552 case UNICHROME_K800:
1553 case UNICHROME_PM800:
1554 case UNICHROME_CN700:
1555 case UNICHROME_CX700:
1556 case UNICHROME_K8M890:
1557 case UNICHROME_P4M890:
1558 case UNICHROME_P4M900:
1559 case UNICHROME_VX800:
1560 viafb_write_reg(SR4A, VIASR, CLK / 0x10000);
1561 viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100);
1562 viafb_write_reg(SR4C, VIASR, CLK % 0x100);
1563 break;
1564 }
1565 }
1566
1567 /* H.W. Reset : OFF */
1568 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1569
1570 /* Reset PLL */
1571 if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
1572 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
1573 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
1574 }
1575
1576 if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
1577 viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
1578 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
1579 }
1580
1581 /* Fire! */
1582 RegTemp = inb(VIARMisc);
1583 outb(RegTemp | (BIT2 + BIT3), VIAWMisc);
1584}
1585
1586void viafb_load_crtc_timing(struct display_timing device_timing,
1587 int set_iga)
1588{
1589 int i;
1590 int viafb_load_reg_num = 0;
1591 int reg_value = 0;
1592 struct io_register *reg = NULL;
1593
1594 viafb_unlock_crt();
1595
1596 for (i = 0; i < 12; i++) {
1597 if (set_iga == IGA1) {
1598 switch (i) {
1599 case H_TOTAL_INDEX:
1600 reg_value =
1601 IGA1_HOR_TOTAL_FORMULA(device_timing.
1602 hor_total);
1603 viafb_load_reg_num =
1604 iga1_crtc_reg.hor_total.reg_num;
1605 reg = iga1_crtc_reg.hor_total.reg;
1606 break;
1607 case H_ADDR_INDEX:
1608 reg_value =
1609 IGA1_HOR_ADDR_FORMULA(device_timing.
1610 hor_addr);
1611 viafb_load_reg_num =
1612 iga1_crtc_reg.hor_addr.reg_num;
1613 reg = iga1_crtc_reg.hor_addr.reg;
1614 break;
1615 case H_BLANK_START_INDEX:
1616 reg_value =
1617 IGA1_HOR_BLANK_START_FORMULA
1618 (device_timing.hor_blank_start);
1619 viafb_load_reg_num =
1620 iga1_crtc_reg.hor_blank_start.reg_num;
1621 reg = iga1_crtc_reg.hor_blank_start.reg;
1622 break;
1623 case H_BLANK_END_INDEX:
1624 reg_value =
1625 IGA1_HOR_BLANK_END_FORMULA
1626 (device_timing.hor_blank_start,
1627 device_timing.hor_blank_end);
1628 viafb_load_reg_num =
1629 iga1_crtc_reg.hor_blank_end.reg_num;
1630 reg = iga1_crtc_reg.hor_blank_end.reg;
1631 break;
1632 case H_SYNC_START_INDEX:
1633 reg_value =
1634 IGA1_HOR_SYNC_START_FORMULA
1635 (device_timing.hor_sync_start);
1636 viafb_load_reg_num =
1637 iga1_crtc_reg.hor_sync_start.reg_num;
1638 reg = iga1_crtc_reg.hor_sync_start.reg;
1639 break;
1640 case H_SYNC_END_INDEX:
1641 reg_value =
1642 IGA1_HOR_SYNC_END_FORMULA
1643 (device_timing.hor_sync_start,
1644 device_timing.hor_sync_end);
1645 viafb_load_reg_num =
1646 iga1_crtc_reg.hor_sync_end.reg_num;
1647 reg = iga1_crtc_reg.hor_sync_end.reg;
1648 break;
1649 case V_TOTAL_INDEX:
1650 reg_value =
1651 IGA1_VER_TOTAL_FORMULA(device_timing.
1652 ver_total);
1653 viafb_load_reg_num =
1654 iga1_crtc_reg.ver_total.reg_num;
1655 reg = iga1_crtc_reg.ver_total.reg;
1656 break;
1657 case V_ADDR_INDEX:
1658 reg_value =
1659 IGA1_VER_ADDR_FORMULA(device_timing.
1660 ver_addr);
1661 viafb_load_reg_num =
1662 iga1_crtc_reg.ver_addr.reg_num;
1663 reg = iga1_crtc_reg.ver_addr.reg;
1664 break;
1665 case V_BLANK_START_INDEX:
1666 reg_value =
1667 IGA1_VER_BLANK_START_FORMULA
1668 (device_timing.ver_blank_start);
1669 viafb_load_reg_num =
1670 iga1_crtc_reg.ver_blank_start.reg_num;
1671 reg = iga1_crtc_reg.ver_blank_start.reg;
1672 break;
1673 case V_BLANK_END_INDEX:
1674 reg_value =
1675 IGA1_VER_BLANK_END_FORMULA
1676 (device_timing.ver_blank_start,
1677 device_timing.ver_blank_end);
1678 viafb_load_reg_num =
1679 iga1_crtc_reg.ver_blank_end.reg_num;
1680 reg = iga1_crtc_reg.ver_blank_end.reg;
1681 break;
1682 case V_SYNC_START_INDEX:
1683 reg_value =
1684 IGA1_VER_SYNC_START_FORMULA
1685 (device_timing.ver_sync_start);
1686 viafb_load_reg_num =
1687 iga1_crtc_reg.ver_sync_start.reg_num;
1688 reg = iga1_crtc_reg.ver_sync_start.reg;
1689 break;
1690 case V_SYNC_END_INDEX:
1691 reg_value =
1692 IGA1_VER_SYNC_END_FORMULA
1693 (device_timing.ver_sync_start,
1694 device_timing.ver_sync_end);
1695 viafb_load_reg_num =
1696 iga1_crtc_reg.ver_sync_end.reg_num;
1697 reg = iga1_crtc_reg.ver_sync_end.reg;
1698 break;
1699
1700 }
1701 }
1702
1703 if (set_iga == IGA2) {
1704 switch (i) {
1705 case H_TOTAL_INDEX:
1706 reg_value =
1707 IGA2_HOR_TOTAL_FORMULA(device_timing.
1708 hor_total);
1709 viafb_load_reg_num =
1710 iga2_crtc_reg.hor_total.reg_num;
1711 reg = iga2_crtc_reg.hor_total.reg;
1712 break;
1713 case H_ADDR_INDEX:
1714 reg_value =
1715 IGA2_HOR_ADDR_FORMULA(device_timing.
1716 hor_addr);
1717 viafb_load_reg_num =
1718 iga2_crtc_reg.hor_addr.reg_num;
1719 reg = iga2_crtc_reg.hor_addr.reg;
1720 break;
1721 case H_BLANK_START_INDEX:
1722 reg_value =
1723 IGA2_HOR_BLANK_START_FORMULA
1724 (device_timing.hor_blank_start);
1725 viafb_load_reg_num =
1726 iga2_crtc_reg.hor_blank_start.reg_num;
1727 reg = iga2_crtc_reg.hor_blank_start.reg;
1728 break;
1729 case H_BLANK_END_INDEX:
1730 reg_value =
1731 IGA2_HOR_BLANK_END_FORMULA
1732 (device_timing.hor_blank_start,
1733 device_timing.hor_blank_end);
1734 viafb_load_reg_num =
1735 iga2_crtc_reg.hor_blank_end.reg_num;
1736 reg = iga2_crtc_reg.hor_blank_end.reg;
1737 break;
1738 case H_SYNC_START_INDEX:
1739 reg_value =
1740 IGA2_HOR_SYNC_START_FORMULA
1741 (device_timing.hor_sync_start);
1742 if (UNICHROME_CN700 <=
1743 viaparinfo->chip_info->gfx_chip_name)
1744 viafb_load_reg_num =
1745 iga2_crtc_reg.hor_sync_start.
1746 reg_num;
1747 else
1748 viafb_load_reg_num = 3;
1749 reg = iga2_crtc_reg.hor_sync_start.reg;
1750 break;
1751 case H_SYNC_END_INDEX:
1752 reg_value =
1753 IGA2_HOR_SYNC_END_FORMULA
1754 (device_timing.hor_sync_start,
1755 device_timing.hor_sync_end);
1756 viafb_load_reg_num =
1757 iga2_crtc_reg.hor_sync_end.reg_num;
1758 reg = iga2_crtc_reg.hor_sync_end.reg;
1759 break;
1760 case V_TOTAL_INDEX:
1761 reg_value =
1762 IGA2_VER_TOTAL_FORMULA(device_timing.
1763 ver_total);
1764 viafb_load_reg_num =
1765 iga2_crtc_reg.ver_total.reg_num;
1766 reg = iga2_crtc_reg.ver_total.reg;
1767 break;
1768 case V_ADDR_INDEX:
1769 reg_value =
1770 IGA2_VER_ADDR_FORMULA(device_timing.
1771 ver_addr);
1772 viafb_load_reg_num =
1773 iga2_crtc_reg.ver_addr.reg_num;
1774 reg = iga2_crtc_reg.ver_addr.reg;
1775 break;
1776 case V_BLANK_START_INDEX:
1777 reg_value =
1778 IGA2_VER_BLANK_START_FORMULA
1779 (device_timing.ver_blank_start);
1780 viafb_load_reg_num =
1781 iga2_crtc_reg.ver_blank_start.reg_num;
1782 reg = iga2_crtc_reg.ver_blank_start.reg;
1783 break;
1784 case V_BLANK_END_INDEX:
1785 reg_value =
1786 IGA2_VER_BLANK_END_FORMULA
1787 (device_timing.ver_blank_start,
1788 device_timing.ver_blank_end);
1789 viafb_load_reg_num =
1790 iga2_crtc_reg.ver_blank_end.reg_num;
1791 reg = iga2_crtc_reg.ver_blank_end.reg;
1792 break;
1793 case V_SYNC_START_INDEX:
1794 reg_value =
1795 IGA2_VER_SYNC_START_FORMULA
1796 (device_timing.ver_sync_start);
1797 viafb_load_reg_num =
1798 iga2_crtc_reg.ver_sync_start.reg_num;
1799 reg = iga2_crtc_reg.ver_sync_start.reg;
1800 break;
1801 case V_SYNC_END_INDEX:
1802 reg_value =
1803 IGA2_VER_SYNC_END_FORMULA
1804 (device_timing.ver_sync_start,
1805 device_timing.ver_sync_end);
1806 viafb_load_reg_num =
1807 iga2_crtc_reg.ver_sync_end.reg_num;
1808 reg = iga2_crtc_reg.ver_sync_end.reg;
1809 break;
1810
1811 }
1812 }
1813 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1814 }
1815
1816 viafb_lock_crt();
1817}
1818
1819void viafb_set_color_depth(int bpp_byte, int set_iga)
1820{
1821 if (set_iga == IGA1) {
1822 switch (bpp_byte) {
1823 case MODE_8BPP:
1824 viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E);
1825 break;
1826 case MODE_16BPP:
1827 viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
1828 break;
1829 case MODE_32BPP:
1830 viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
1831 break;
1832 }
1833 } else {
1834 switch (bpp_byte) {
1835 case MODE_8BPP:
1836 viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7);
1837 break;
1838 case MODE_16BPP:
1839 viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7);
1840 break;
1841 case MODE_32BPP:
1842 viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7);
1843 break;
1844 }
1845 }
1846}
1847
1848void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1849 int mode_index, int bpp_byte, int set_iga)
1850{
1851 struct VideoModeTable *video_mode;
1852 struct display_timing crt_reg;
1853 int i;
1854 int index = 0;
1855 int h_addr, v_addr;
1856 u32 pll_D_N;
1857
1858 video_mode = &CLE266Modes[search_mode_setting(mode_index)];
1859
1860 for (i = 0; i < video_mode->mode_array; i++) {
1861 index = i;
1862
1863 if (crt_table[i].refresh_rate == viaparinfo->
1864 crt_setting_info->refresh_rate)
1865 break;
1866 }
1867
1868 crt_reg = crt_table[index].crtc;
1869
1870 /* Mode 640x480 has border, but LCD/DFP didn't have border. */
1871 /* So we would delete border. */
1872 if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480)
1873 && (viaparinfo->crt_setting_info->refresh_rate == 60)) {
1874 /* The border is 8 pixels. */
1875 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
1876
1877 /* Blanking time should add left and right borders. */
1878 crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
1879 }
1880
1881 h_addr = crt_reg.hor_addr;
1882 v_addr = crt_reg.ver_addr;
1883
1884 /* update polarity for CRT timing */
1885 if (crt_table[index].h_sync_polarity == NEGATIVE) {
1886 if (crt_table[index].v_sync_polarity == NEGATIVE)
1887 outb((inb(VIARMisc) & (~(BIT6 + BIT7))) |
1888 (BIT6 + BIT7), VIAWMisc);
1889 else
1890 outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6),
1891 VIAWMisc);
1892 } else {
1893 if (crt_table[index].v_sync_polarity == NEGATIVE)
1894 outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7),
1895 VIAWMisc);
1896 else
1897 outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc);
1898 }
1899
1900 if (set_iga == IGA1) {
1901 viafb_unlock_crt();
1902 viafb_write_reg(CR09, VIACR, 0x00); /*initial CR09=0 */
1903 viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6);
1904 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1905 }
1906
1907 switch (set_iga) {
1908 case IGA1:
1909 viafb_load_crtc_timing(crt_reg, IGA1);
1910 break;
1911 case IGA2:
1912 viafb_load_crtc_timing(crt_reg, IGA2);
1913 break;
1914 }
1915
1916 load_fix_bit_crtc_reg();
1917 viafb_lock_crt();
1918 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1919 viafb_load_offset_reg(h_addr, bpp_byte, set_iga);
1920 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
1921
1922 /* load FIFO */
1923 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1924 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1925 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
1926
1927 /* load SR Register About Memory and Color part */
1928 viafb_set_color_depth(bpp_byte, set_iga);
1929
1930 pll_D_N = viafb_get_clk_value(crt_table[index].clk);
1931 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
1932 viafb_set_vclock(pll_D_N, set_iga);
1933
1934}
1935
1936void viafb_init_chip_info(void)
1937{
1938 init_gfx_chip_info();
1939 init_tmds_chip_info();
1940 init_lvds_chip_info();
1941
1942 viaparinfo->crt_setting_info->iga_path = IGA1;
1943 viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
1944
1945 /*Set IGA path for each device */
1946 viafb_set_iga_path();
1947
1948 viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
1949 viaparinfo->lvds_setting_info->get_lcd_size_method =
1950 GET_LCD_SIZE_BY_USER_SETTING;
1951 viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
1952 viaparinfo->lvds_setting_info2->display_method =
1953 viaparinfo->lvds_setting_info->display_method;
1954 viaparinfo->lvds_setting_info2->lcd_mode =
1955 viaparinfo->lvds_setting_info->lcd_mode;
1956}
1957
1958void viafb_update_device_setting(int hres, int vres,
1959 int bpp, int vmode_refresh, int flag)
1960{
1961 if (flag == 0) {
1962 viaparinfo->crt_setting_info->h_active = hres;
1963 viaparinfo->crt_setting_info->v_active = vres;
1964 viaparinfo->crt_setting_info->bpp = bpp;
1965 viaparinfo->crt_setting_info->refresh_rate =
1966 vmode_refresh;
1967
1968 viaparinfo->tmds_setting_info->h_active = hres;
1969 viaparinfo->tmds_setting_info->v_active = vres;
1970 viaparinfo->tmds_setting_info->bpp = bpp;
1971 viaparinfo->tmds_setting_info->refresh_rate =
1972 vmode_refresh;
1973
1974 viaparinfo->lvds_setting_info->h_active = hres;
1975 viaparinfo->lvds_setting_info->v_active = vres;
1976 viaparinfo->lvds_setting_info->bpp = bpp;
1977 viaparinfo->lvds_setting_info->refresh_rate =
1978 vmode_refresh;
1979 viaparinfo->lvds_setting_info2->h_active = hres;
1980 viaparinfo->lvds_setting_info2->v_active = vres;
1981 viaparinfo->lvds_setting_info2->bpp = bpp;
1982 viaparinfo->lvds_setting_info2->refresh_rate =
1983 vmode_refresh;
1984 } else {
1985
1986 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
1987 viaparinfo->tmds_setting_info->h_active = hres;
1988 viaparinfo->tmds_setting_info->v_active = vres;
1989 viaparinfo->tmds_setting_info->bpp = bpp;
1990 viaparinfo->tmds_setting_info->refresh_rate =
1991 vmode_refresh;
1992 }
1993
1994 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
1995 viaparinfo->lvds_setting_info->h_active = hres;
1996 viaparinfo->lvds_setting_info->v_active = vres;
1997 viaparinfo->lvds_setting_info->bpp = bpp;
1998 viaparinfo->lvds_setting_info->refresh_rate =
1999 vmode_refresh;
2000 }
2001 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
2002 viaparinfo->lvds_setting_info2->h_active = hres;
2003 viaparinfo->lvds_setting_info2->v_active = vres;
2004 viaparinfo->lvds_setting_info2->bpp = bpp;
2005 viaparinfo->lvds_setting_info2->refresh_rate =
2006 vmode_refresh;
2007 }
2008 }
2009}
2010
2011static void init_gfx_chip_info(void)
2012{
2013 struct pci_dev *pdev = NULL;
2014 u32 i;
2015 u8 tmp;
2016
2017 /* Indentify GFX Chip Name */
2018 for (i = 0; pciidlist[i].vendor != 0; i++) {
2019 pdev = pci_get_device(pciidlist[i].vendor,
2020 pciidlist[i].device, 0);
2021 if (pdev)
2022 break;
2023 }
2024
2025 if (!pciidlist[i].vendor)
2026 return ;
2027
2028 viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index;
2029
2030 /* Check revision of CLE266 Chip */
2031 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
2032 /* CR4F only define in CLE266.CX chip */
2033 tmp = viafb_read_reg(VIACR, CR4F);
2034 viafb_write_reg(CR4F, VIACR, 0x55);
2035 if (viafb_read_reg(VIACR, CR4F) != 0x55)
2036 viaparinfo->chip_info->gfx_chip_revision =
2037 CLE266_REVISION_AX;
2038 else
2039 viaparinfo->chip_info->gfx_chip_revision =
2040 CLE266_REVISION_CX;
2041 /* restore orignal CR4F value */
2042 viafb_write_reg(CR4F, VIACR, tmp);
2043 }
2044
2045 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
2046 tmp = viafb_read_reg(VIASR, SR43);
2047 DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
2048 if (tmp & 0x02) {
2049 viaparinfo->chip_info->gfx_chip_revision =
2050 CX700_REVISION_700M2;
2051 } else if (tmp & 0x40) {
2052 viaparinfo->chip_info->gfx_chip_revision =
2053 CX700_REVISION_700M;
2054 } else {
2055 viaparinfo->chip_info->gfx_chip_revision =
2056 CX700_REVISION_700;
2057 }
2058 }
2059
2060 pci_dev_put(pdev);
2061}
2062
2063static void init_tmds_chip_info(void)
2064{
2065 viafb_tmds_trasmitter_identify();
2066
2067 if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
2068 output_interface) {
2069 switch (viaparinfo->chip_info->gfx_chip_name) {
2070 case UNICHROME_CX700:
2071 {
2072 /* we should check support by hardware layout.*/
2073 if ((viafb_display_hardware_layout ==
2074 HW_LAYOUT_DVI_ONLY)
2075 || (viafb_display_hardware_layout ==
2076 HW_LAYOUT_LCD_DVI)) {
2077 viaparinfo->chip_info->tmds_chip_info.
2078 output_interface = INTERFACE_TMDS;
2079 } else {
2080 viaparinfo->chip_info->tmds_chip_info.
2081 output_interface =
2082 INTERFACE_NONE;
2083 }
2084 break;
2085 }
2086 case UNICHROME_K8M890:
2087 case UNICHROME_P4M900:
2088 case UNICHROME_P4M890:
2089 /* TMDS on PCIE, we set DFPLOW as default. */
2090 viaparinfo->chip_info->tmds_chip_info.output_interface =
2091 INTERFACE_DFP_LOW;
2092 break;
2093 default:
2094 {
2095 /* set DVP1 default for DVI */
2096 viaparinfo->chip_info->tmds_chip_info
2097 .output_interface = INTERFACE_DVP1;
2098 }
2099 }
2100 }
2101
2102 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
2103 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
2104 viaparinfo->tmds_setting_info->get_dvi_size_method =
2105 GET_DVI_SIZE_BY_VGA_BIOS;
2106 viafb_init_dvi_size();
2107}
2108
2109static void init_lvds_chip_info(void)
2110{
2111 if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM)
2112 viaparinfo->lvds_setting_info->get_lcd_size_method =
2113 GET_LCD_SIZE_BY_VGA_BIOS;
2114 else
2115 viaparinfo->lvds_setting_info->get_lcd_size_method =
2116 GET_LCD_SIZE_BY_USER_SETTING;
2117
2118 viafb_lvds_trasmitter_identify();
2119 viafb_init_lcd_size();
2120 viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
2121 viaparinfo->lvds_setting_info);
2122 if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2123 viafb_init_lvds_output_interface(&viaparinfo->chip_info->
2124 lvds_chip_info2, viaparinfo->lvds_setting_info2);
2125 }
2126 /*If CX700,two singel LCD, we need to reassign
2127 LCD interface to different LVDS port */
2128 if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
2129 && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
2130 if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
2131 lvds_chip_name) && (INTEGRATED_LVDS ==
2132 viaparinfo->chip_info->
2133 lvds_chip_info2.lvds_chip_name)) {
2134 viaparinfo->chip_info->lvds_chip_info.output_interface =
2135 INTERFACE_LVDS0;
2136 viaparinfo->chip_info->lvds_chip_info2.
2137 output_interface =
2138 INTERFACE_LVDS1;
2139 }
2140 }
2141
2142 DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
2143 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
2144 DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
2145 viaparinfo->chip_info->lvds_chip_info.output_interface);
2146 DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
2147 viaparinfo->chip_info->lvds_chip_info.output_interface);
2148}
2149
2150void viafb_init_dac(int set_iga)
2151{
2152 int i;
2153 u8 tmp;
2154
2155 if (set_iga == IGA1) {
2156 /* access Primary Display's LUT */
2157 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2158 /* turn off LCK */
2159 viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
2160 for (i = 0; i < 256; i++) {
2161 write_dac_reg(i, palLUT_table[i].red,
2162 palLUT_table[i].green,
2163 palLUT_table[i].blue);
2164 }
2165 /* turn on LCK */
2166 viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
2167 } else {
2168 tmp = viafb_read_reg(VIACR, CR6A);
2169 /* access Secondary Display's LUT */
2170 viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
2171 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
2172 for (i = 0; i < 256; i++) {
2173 write_dac_reg(i, palLUT_table[i].red,
2174 palLUT_table[i].green,
2175 palLUT_table[i].blue);
2176 }
2177 /* set IGA1 DAC for default */
2178 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2179 viafb_write_reg(CR6A, VIACR, tmp);
2180 }
2181}
2182
2183static void device_screen_off(void)
2184{
2185 /* turn off CRT screen (IGA1) */
2186 viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
2187}
2188
2189static void device_screen_on(void)
2190{
2191 /* turn on CRT screen (IGA1) */
2192 viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
2193}
2194
2195static void set_display_channel(void)
2196{
2197 /*If viafb_LCD2_ON, on cx700, internal lvds's information
2198 is keeped on lvds_setting_info2 */
2199 if (viafb_LCD2_ON &&
2200 viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
2201 /* For dual channel LCD: */
2202 /* Set to Dual LVDS channel. */
2203 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2204 } else if (viafb_LCD_ON && viafb_DVI_ON) {
2205 /* For LCD+DFP: */
2206 /* Set to LVDS1 + TMDS channel. */
2207 viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
2208 } else if (viafb_DVI_ON) {
2209 /* Set to single TMDS channel. */
2210 viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
2211 } else if (viafb_LCD_ON) {
2212 if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
2213 /* For dual channel LCD: */
2214 /* Set to Dual LVDS channel. */
2215 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2216 } else {
2217 /* Set to LVDS0 + LVDS1 channel. */
2218 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
2219 }
2220 }
2221}
2222
2223int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2224 int vmode_index1, int hor_res1, int ver_res1, int video_bpp1)
2225{
2226 int i, j;
2227 int port;
2228 u8 value, index, mask;
2229 struct VideoModeTable *vmode_tbl;
2230 struct crt_mode_table *crt_timing;
2231 struct VideoModeTable *vmode_tbl1 = NULL;
2232 struct crt_mode_table *crt_timing1 = NULL;
2233
2234 DEBUG_MSG(KERN_INFO "Set Mode!!\n");
2235 DEBUG_MSG(KERN_INFO
2236 "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n",
2237 vmode_index, hor_res, ver_res, video_bpp);
2238
2239 device_screen_off();
2240 vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)];
2241 crt_timing = vmode_tbl->crtc;
2242
2243 if (viafb_SAMM_ON == 1) {
2244 vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)];
2245 crt_timing1 = vmode_tbl1->crtc;
2246 }
2247
2248 inb(VIAStatus);
2249 outb(0x00, VIAAR);
2250
2251 /* Write Common Setting for Video Mode */
2252 switch (viaparinfo->chip_info->gfx_chip_name) {
2253 case UNICHROME_CLE266:
2254 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
2255 break;
2256
2257 case UNICHROME_K400:
2258 viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
2259 break;
2260
2261 case UNICHROME_K800:
2262 case UNICHROME_PM800:
2263 viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
2264 break;
2265
2266 case UNICHROME_CN700:
2267 case UNICHROME_K8M890:
2268 case UNICHROME_P4M890:
2269 case UNICHROME_P4M900:
2270 viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
2271 break;
2272
2273 case UNICHROME_CX700:
2274 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
2275
2276 case UNICHROME_VX800:
2277 viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs);
2278
2279 break;
2280 }
2281
2282 device_off();
2283
2284 /* Fill VPIT Parameters */
2285 /* Write Misc Register */
2286 outb(VPIT.Misc, VIAWMisc);
2287
2288 /* Write Sequencer */
2289 for (i = 1; i <= StdSR; i++) {
2290 outb(i, VIASR);
2291 outb(VPIT.SR[i - 1], VIASR + 1);
2292 }
2293
2294 viafb_set_start_addr();
2295 viafb_set_iga_path();
2296
2297 /* Write CRTC */
2298 viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1);
2299
2300 /* Write Graphic Controller */
2301 for (i = 0; i < StdGR; i++) {
2302 outb(i, VIAGR);
2303 outb(VPIT.GR[i], VIAGR + 1);
2304 }
2305
2306 /* Write Attribute Controller */
2307 for (i = 0; i < StdAR; i++) {
2308 inb(VIAStatus);
2309 outb(i, VIAAR);
2310 outb(VPIT.AR[i], VIAAR);
2311 }
2312
2313 inb(VIAStatus);
2314 outb(0x20, VIAAR);
2315
2316 /* Update Patch Register */
2317
2318 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
2319 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) {
2320 for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
2321 if (res_patch_table[i].mode_index == vmode_index) {
2322 for (j = 0;
2323 j < res_patch_table[i].table_length; j++) {
2324 index =
2325 res_patch_table[i].
2326 io_reg_table[j].index;
2327 port =
2328 res_patch_table[i].
2329 io_reg_table[j].port;
2330 value =
2331 res_patch_table[i].
2332 io_reg_table[j].value;
2333 mask =
2334 res_patch_table[i].
2335 io_reg_table[j].mask;
2336 viafb_write_reg_mask(index, port, value,
2337 mask);
2338 }
2339 }
2340 }
2341 }
2342
2343 if (viafb_SAMM_ON == 1) {
2344 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
2345 || (viaparinfo->chip_info->gfx_chip_name ==
2346 UNICHROME_K400)) {
2347 for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
2348 if (res_patch_table[i].mode_index ==
2349 vmode_index1) {
2350 for (j = 0;
2351 j <
2352 res_patch_table[i].
2353 table_length; j++) {
2354 index =
2355 res_patch_table[i].
2356 io_reg_table[j].index;
2357 port =
2358 res_patch_table[i].
2359 io_reg_table[j].port;
2360 value =
2361 res_patch_table[i].
2362 io_reg_table[j].value;
2363 mask =
2364 res_patch_table[i].
2365 io_reg_table[j].mask;
2366 viafb_write_reg_mask(index,
2367 port, value, mask);
2368 }
2369 }
2370 }
2371 }
2372 }
2373
2374 /* Update Refresh Rate Setting */
2375
2376 /* Clear On Screen */
2377
2378 /* CRT set mode */
2379 if (viafb_CRT_ON) {
2380 if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
2381 IGA2)) {
2382 viafb_fill_crtc_timing(crt_timing1, vmode_index1,
2383 video_bpp1 / 8,
2384 viaparinfo->crt_setting_info->iga_path);
2385 } else {
2386 viafb_fill_crtc_timing(crt_timing, vmode_index,
2387 video_bpp / 8,
2388 viaparinfo->crt_setting_info->iga_path);
2389 }
2390
2391 set_crt_output_path(viaparinfo->crt_setting_info->iga_path);
2392
2393 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2394 to 8 alignment (1368),there is several pixels (2 pixels)
2395 on right side of screen. */
2396 if (hor_res % 8) {
2397 viafb_unlock_crt();
2398 viafb_write_reg(CR02, VIACR,
2399 viafb_read_reg(VIACR, CR02) - 1);
2400 viafb_lock_crt();
2401 }
2402 }
2403
2404 if (viafb_DVI_ON) {
2405 if (viafb_SAMM_ON &&
2406 (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
2407 viafb_dvi_set_mode(viafb_get_mode_index
2408 (viaparinfo->tmds_setting_info->h_active,
2409 viaparinfo->tmds_setting_info->
2410 v_active, 1),
2411 video_bpp1, viaparinfo->
2412 tmds_setting_info->iga_path);
2413 } else {
2414 viafb_dvi_set_mode(viafb_get_mode_index
2415 (viaparinfo->tmds_setting_info->h_active,
2416 viaparinfo->
2417 tmds_setting_info->v_active, 0),
2418 video_bpp, viaparinfo->
2419 tmds_setting_info->iga_path);
2420 }
2421 }
2422
2423 if (viafb_LCD_ON) {
2424 if (viafb_SAMM_ON &&
2425 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
2426 viaparinfo->lvds_setting_info->bpp = video_bpp1;
2427 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2428 lvds_setting_info,
2429 &viaparinfo->chip_info->lvds_chip_info);
2430 } else {
2431 /* IGA1 doesn't have LCD scaling, so set it center. */
2432 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
2433 viaparinfo->lvds_setting_info->display_method =
2434 LCD_CENTERING;
2435 }
2436 viaparinfo->lvds_setting_info->bpp = video_bpp;
2437 viafb_lcd_set_mode(crt_timing, viaparinfo->
2438 lvds_setting_info,
2439 &viaparinfo->chip_info->lvds_chip_info);
2440 }
2441 }
2442 if (viafb_LCD2_ON) {
2443 if (viafb_SAMM_ON &&
2444 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
2445 viaparinfo->lvds_setting_info2->bpp = video_bpp1;
2446 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2447 lvds_setting_info2,
2448 &viaparinfo->chip_info->lvds_chip_info2);
2449 } else {
2450 /* IGA1 doesn't have LCD scaling, so set it center. */
2451 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
2452 viaparinfo->lvds_setting_info2->display_method =
2453 LCD_CENTERING;
2454 }
2455 viaparinfo->lvds_setting_info2->bpp = video_bpp;
2456 viafb_lcd_set_mode(crt_timing, viaparinfo->
2457 lvds_setting_info2,
2458 &viaparinfo->chip_info->lvds_chip_info2);
2459 }
2460 }
2461
2462 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
2463 && (viafb_LCD_ON || viafb_DVI_ON))
2464 set_display_channel();
2465
2466 /* If set mode normally, save resolution information for hot-plug . */
2467 if (!viafb_hotplug) {
2468 viafb_hotplug_Xres = hor_res;
2469 viafb_hotplug_Yres = ver_res;
2470 viafb_hotplug_bpp = video_bpp;
2471 viafb_hotplug_refresh = viafb_refresh;
2472
2473 if (viafb_DVI_ON)
2474 viafb_DeviceStatus = DVI_Device;
2475 else
2476 viafb_DeviceStatus = CRT_Device;
2477 }
2478 device_on();
2479
2480 if (viafb_SAMM_ON == 1)
2481 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
2482
2483 device_screen_on();
2484 return 1;
2485}
2486
2487int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
2488{
2489 int i;
2490
2491 for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
2492 if ((hres == res_map_refresh_tbl[i].hres)
2493 && (vres == res_map_refresh_tbl[i].vres)
2494 && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh))
2495 return res_map_refresh_tbl[i].pixclock;
2496 }
2497 return RES_640X480_60HZ_PIXCLOCK;
2498
2499}
2500
2501int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2502{
2503#define REFRESH_TOLERANCE 3
2504 int i, nearest = -1, diff = REFRESH_TOLERANCE;
2505 for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
2506 if ((hres == res_map_refresh_tbl[i].hres)
2507 && (vres == res_map_refresh_tbl[i].vres)
2508 && (diff > (abs(long_refresh -
2509 res_map_refresh_tbl[i].vmode_refresh)))) {
2510 diff = abs(long_refresh - res_map_refresh_tbl[i].
2511 vmode_refresh);
2512 nearest = i;
2513 }
2514 }
2515#undef REFRESH_TOLERANCE
2516 if (nearest > 0)
2517 return res_map_refresh_tbl[nearest].vmode_refresh;
2518 return 60;
2519}
2520
2521static void device_off(void)
2522{
2523 viafb_crt_disable();
2524 viafb_dvi_disable();
2525 viafb_lcd_disable();
2526}
2527
2528static void device_on(void)
2529{
2530 if (viafb_CRT_ON == 1)
2531 viafb_crt_enable();
2532 if (viafb_DVI_ON == 1)
2533 viafb_dvi_enable();
2534 if (viafb_LCD_ON == 1)
2535 viafb_lcd_enable();
2536}
2537
2538void viafb_crt_disable(void)
2539{
2540 viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
2541}
2542
2543void viafb_crt_enable(void)
2544{
2545 viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
2546}
2547
2548void viafb_get_mmio_info(unsigned long *mmio_base,
2549 unsigned long *mmio_len)
2550{
2551 struct pci_dev *pdev = NULL;
2552 u32 vendor, device;
2553 u32 i;
2554
2555 for (i = 0; pciidlist[i].vendor != 0; i++)
2556 if (viaparinfo->chip_info->gfx_chip_name ==
2557 pciidlist[i].chip_index)
2558 break;
2559
2560 if (!pciidlist[i].vendor)
2561 return ;
2562
2563 vendor = pciidlist[i].vendor;
2564 device = pciidlist[i].device;
2565
2566 pdev = pci_get_device(vendor, device, NULL);
2567
2568 if (!pdev) {
2569 *mmio_base = 0;
2570 *mmio_len = 0;
2571 return ;
2572 }
2573
2574 *mmio_base = pci_resource_start(pdev, 1);
2575 *mmio_len = pci_resource_len(pdev, 1);
2576
2577 pci_dev_put(pdev);
2578}
2579
2580static void enable_second_display_channel(void)
2581{
2582 /* to enable second display channel. */
2583 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2584 viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
2585 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2586}
2587
2588static void disable_second_display_channel(void)
2589{
2590 /* to disable second display channel. */
2591 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2592 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
2593 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2594}
2595
2596void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len)
2597{
2598 struct pci_dev *pdev = NULL;
2599 u32 vendor, device;
2600 u32 i;
2601
2602 for (i = 0; pciidlist[i].vendor != 0; i++)
2603 if (viaparinfo->chip_info->gfx_chip_name ==
2604 pciidlist[i].chip_index)
2605 break;
2606
2607 if (!pciidlist[i].vendor)
2608 return ;
2609
2610 vendor = pciidlist[i].vendor;
2611 device = pciidlist[i].device;
2612
2613 pdev = pci_get_device(vendor, device, NULL);
2614
2615 if (!pdev) {
2616 *fb_base = viafb_read_reg(VIASR, SR30) << 24;
2617 *fb_len = viafb_get_memsize();
2618 DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n");
2619 DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
2620 DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
2621 return ;
2622 }
2623
2624 *fb_base = (unsigned int)pci_resource_start(pdev, 0);
2625 *fb_len = get_fb_size_from_pci();
2626 DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n");
2627 DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
2628 DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
2629
2630 pci_dev_put(pdev);
2631}
2632
2633static int get_fb_size_from_pci(void)
2634{
2635 unsigned long configid, deviceid, FBSize = 0;
2636 int VideoMemSize;
2637 int DeviceFound = false;
2638
2639 for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) {
2640 outl(configid, (unsigned long)0xCF8);
2641 deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff;
2642
2643 switch (deviceid) {
2644 case CLE266:
2645 case KM400:
2646 outl(configid + 0xE0, (unsigned long)0xCF8);
2647 FBSize = inl((unsigned long)0xCFC);
2648 DeviceFound = true; /* Found device id */
2649 break;
2650
2651 case CN400_FUNCTION3:
2652 case CN700_FUNCTION3:
2653 case CX700_FUNCTION3:
2654 case KM800_FUNCTION3:
2655 case KM890_FUNCTION3:
2656 case P4M890_FUNCTION3:
2657 case P4M900_FUNCTION3:
2658 case VX800_FUNCTION3:
2659 /*case CN750_FUNCTION3: */
2660 outl(configid + 0xA0, (unsigned long)0xCF8);
2661 FBSize = inl((unsigned long)0xCFC);
2662 DeviceFound = true; /* Found device id */
2663 break;
2664
2665 default:
2666 break;
2667 }
2668
2669 if (DeviceFound)
2670 break;
2671 }
2672
2673 DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid);
2674
2675 FBSize = FBSize & 0x00007000;
2676 DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
2677
2678 if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) {
2679 switch (FBSize) {
2680 case 0x00004000:
2681 VideoMemSize = (16 << 20); /*16M */
2682 break;
2683
2684 case 0x00005000:
2685 VideoMemSize = (32 << 20); /*32M */
2686 break;
2687
2688 case 0x00006000:
2689 VideoMemSize = (64 << 20); /*64M */
2690 break;
2691
2692 default:
2693 VideoMemSize = (32 << 20); /*32M */
2694 break;
2695 }
2696 } else {
2697 switch (FBSize) {
2698 case 0x00001000:
2699 VideoMemSize = (8 << 20); /*8M */
2700 break;
2701
2702 case 0x00002000:
2703 VideoMemSize = (16 << 20); /*16M */
2704 break;
2705
2706 case 0x00003000:
2707 VideoMemSize = (32 << 20); /*32M */
2708 break;
2709
2710 case 0x00004000:
2711 VideoMemSize = (64 << 20); /*64M */
2712 break;
2713
2714 case 0x00005000:
2715 VideoMemSize = (128 << 20); /*128M */
2716 break;
2717
2718 case 0x00006000:
2719 VideoMemSize = (256 << 20); /*256M */
2720 break;
2721
2722 default:
2723 VideoMemSize = (32 << 20); /*32M */
2724 break;
2725 }
2726 }
2727
2728 return VideoMemSize;
2729}
2730
2731void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2732 *p_gfx_dpa_setting)
2733{
2734 switch (output_interface) {
2735 case INTERFACE_DVP0:
2736 {
2737 /* DVP0 Clock Polarity and Adjust: */
2738 viafb_write_reg_mask(CR96, VIACR,
2739 p_gfx_dpa_setting->DVP0, 0x0F);
2740
2741 /* DVP0 Clock and Data Pads Driving: */
2742 viafb_write_reg_mask(SR1E, VIASR,
2743 p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
2744 viafb_write_reg_mask(SR2A, VIASR,
2745 p_gfx_dpa_setting->DVP0ClockDri_S1,
2746 BIT4);
2747 viafb_write_reg_mask(SR1B, VIASR,
2748 p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
2749 viafb_write_reg_mask(SR2A, VIASR,
2750 p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
2751 break;
2752 }
2753
2754 case INTERFACE_DVP1:
2755 {
2756 /* DVP1 Clock Polarity and Adjust: */
2757 viafb_write_reg_mask(CR9B, VIACR,
2758 p_gfx_dpa_setting->DVP1, 0x0F);
2759
2760 /* DVP1 Clock and Data Pads Driving: */
2761 viafb_write_reg_mask(SR65, VIASR,
2762 p_gfx_dpa_setting->DVP1Driving, 0x0F);
2763 break;
2764 }
2765
2766 case INTERFACE_DFP_HIGH:
2767 {
2768 viafb_write_reg_mask(CR97, VIACR,
2769 p_gfx_dpa_setting->DFPHigh, 0x0F);
2770 break;
2771 }
2772
2773 case INTERFACE_DFP_LOW:
2774 {
2775 viafb_write_reg_mask(CR99, VIACR,
2776 p_gfx_dpa_setting->DFPLow, 0x0F);
2777 break;
2778 }
2779
2780 case INTERFACE_DFP:
2781 {
2782 viafb_write_reg_mask(CR97, VIACR,
2783 p_gfx_dpa_setting->DFPHigh, 0x0F);
2784 viafb_write_reg_mask(CR99, VIACR,
2785 p_gfx_dpa_setting->DFPLow, 0x0F);
2786 break;
2787 }
2788 }
2789}
2790
2791void viafb_memory_pitch_patch(struct fb_info *info)
2792{
2793 if (info->var.xres != info->var.xres_virtual) {
2794 viafb_load_offset_reg(info->var.xres_virtual,
2795 info->var.bits_per_pixel >> 3, IGA1);
2796
2797 if (viafb_SAMM_ON) {
2798 viafb_load_offset_reg(viafb_second_virtual_xres,
2799 viafb_bpp1 >> 3,
2800 IGA2);
2801 } else {
2802 viafb_load_offset_reg(info->var.xres_virtual,
2803 info->var.bits_per_pixel >> 3, IGA2);
2804 }
2805
2806 }
2807}
2808
2809/*According var's xres, yres fill var's other timing information*/
2810void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2811 int mode_index)
2812{
2813 struct VideoModeTable *vmode_tbl = NULL;
2814 struct crt_mode_table *crt_timing = NULL;
2815 struct display_timing crt_reg;
2816 int i = 0, index = 0;
2817 vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)];
2818 crt_timing = vmode_tbl->crtc;
2819 for (i = 0; i < vmode_tbl->mode_array; i++) {
2820 index = i;
2821 if (crt_timing[i].refresh_rate == refresh)
2822 break;
2823 }
2824
2825 crt_reg = crt_timing[index].crtc;
2826 switch (var->bits_per_pixel) {
2827 case 8:
2828 var->red.offset = 0;
2829 var->green.offset = 0;
2830 var->blue.offset = 0;
2831 var->red.length = 6;
2832 var->green.length = 6;
2833 var->blue.length = 6;
2834 break;
2835 case 16:
2836 var->red.offset = 11;
2837 var->green.offset = 5;
2838 var->blue.offset = 0;
2839 var->red.length = 5;
2840 var->green.length = 6;
2841 var->blue.length = 5;
2842 break;
2843 case 32:
2844 var->red.offset = 16;
2845 var->green.offset = 8;
2846 var->blue.offset = 0;
2847 var->red.length = 8;
2848 var->green.length = 8;
2849 var->blue.length = 8;
2850 break;
2851 default:
2852 /* never happed, put here to keep consistent */
2853 break;
2854 }
2855
2856 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
2857 var->left_margin =
2858 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
2859 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
2860 var->hsync_len = crt_reg.hor_sync_end;
2861 var->upper_margin =
2862 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2863 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2864 var->vsync_len = crt_reg.ver_sync_end;
2865}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
new file mode 100644
index 000000000000..6ff38fa8569a
--- /dev/null
+++ b/drivers/video/via/hw.h
@@ -0,0 +1,933 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __HW_H__
23#define __HW_H__
24
25#include "global.h"
26
27/***************************************************
28* Definition IGA1 Design Method of CRTC Registers *
29****************************************************/
30#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5)
31#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1)
32#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1)
33#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1)
34#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8)
35#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8)
36
37#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2)
38#define IGA1_VER_ADDR_FORMULA(x) ((x)-1)
39#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1)
40#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
41#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1)
42#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
43
44/***************************************************
45** Definition IGA2 Design Method of CRTC Registers *
46****************************************************/
47#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1)
48#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1)
49#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1)
50#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1)
51#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1)
52#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1)
53
54#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1)
55#define IGA2_VER_ADDR_FORMULA(x) ((x)-1)
56#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1)
57#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
58#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1)
59#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
60
61/**********************************************************/
62/* Definition IGA2 Design Method of CRTC Shadow Registers */
63/**********************************************************/
64#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x) ((x/8)-5)
65#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y) (((x+y)/8)-1)
66#define IGA2_VER_TOTAL_SHADOW_FORMULA(x) ((x)-2)
67#define IGA2_VER_ADDR_SHADOW_FORMULA(x) ((x)-1)
68#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x) ((x)-1)
69#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y) ((x+y)-1)
70#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
71#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
72
73/* Define Register Number for IGA1 CRTC Timing */
74
75/* location: {CR00,0,7},{CR36,3,3} */
76#define IGA1_HOR_TOTAL_REG_NUM 2
77/* location: {CR01,0,7} */
78#define IGA1_HOR_ADDR_REG_NUM 1
79/* location: {CR02,0,7} */
80#define IGA1_HOR_BLANK_START_REG_NUM 1
81/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
82#define IGA1_HOR_BLANK_END_REG_NUM 3
83/* location: {CR04,0,7},{CR33,4,4} */
84#define IGA1_HOR_SYNC_START_REG_NUM 2
85/* location: {CR05,0,4} */
86#define IGA1_HOR_SYNC_END_REG_NUM 1
87/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
88#define IGA1_VER_TOTAL_REG_NUM 4
89/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
90#define IGA1_VER_ADDR_REG_NUM 4
91/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
92#define IGA1_VER_BLANK_START_REG_NUM 4
93/* location: {CR16,0,7} */
94#define IGA1_VER_BLANK_END_REG_NUM 1
95/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
96#define IGA1_VER_SYNC_START_REG_NUM 4
97/* location: {CR11,0,3} */
98#define IGA1_VER_SYNC_END_REG_NUM 1
99
100/* Define Register Number for IGA2 Shadow CRTC Timing */
101
102/* location: {CR6D,0,7},{CR71,3,3} */
103#define IGA2_SHADOW_HOR_TOTAL_REG_NUM 2
104/* location: {CR6E,0,7} */
105#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM 1
106/* location: {CR6F,0,7},{CR71,0,2} */
107#define IGA2_SHADOW_VER_TOTAL_REG_NUM 2
108/* location: {CR70,0,7},{CR71,4,6} */
109#define IGA2_SHADOW_VER_ADDR_REG_NUM 2
110/* location: {CR72,0,7},{CR74,4,6} */
111#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
112/* location: {CR73,0,7},{CR74,0,2} */
113#define IGA2_SHADOW_VER_BLANK_END_REG_NUM 2
114/* location: {CR75,0,7},{CR76,4,6} */
115#define IGA2_SHADOW_VER_SYNC_START_REG_NUM 2
116/* location: {CR76,0,3} */
117#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
118
119/* Define Register Number for IGA2 CRTC Timing */
120
121/* location: {CR50,0,7},{CR55,0,3} */
122#define IGA2_HOR_TOTAL_REG_NUM 2
123/* location: {CR51,0,7},{CR55,4,6} */
124#define IGA2_HOR_ADDR_REG_NUM 2
125/* location: {CR52,0,7},{CR54,0,2} */
126#define IGA2_HOR_BLANK_START_REG_NUM 2
127/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
128is reserved, so it may have problem to set 1600x1200 on IGA2. */
129/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
130#define IGA2_HOR_BLANK_END_REG_NUM 3
131/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
132/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
133#define IGA2_HOR_SYNC_START_REG_NUM 4
134
135/* location: {CR57,0,7},{CR5C,6,6} */
136#define IGA2_HOR_SYNC_END_REG_NUM 2
137/* location: {CR58,0,7},{CR5D,0,2} */
138#define IGA2_VER_TOTAL_REG_NUM 2
139/* location: {CR59,0,7},{CR5D,3,5} */
140#define IGA2_VER_ADDR_REG_NUM 2
141/* location: {CR5A,0,7},{CR5C,0,2} */
142#define IGA2_VER_BLANK_START_REG_NUM 2
143/* location: {CR5E,0,7},{CR5C,3,5} */
144#define IGA2_VER_BLANK_END_REG_NUM 2
145/* location: {CR5E,0,7},{CR5F,5,7} */
146#define IGA2_VER_SYNC_START_REG_NUM 2
147/* location: {CR5F,0,4} */
148#define IGA2_VER_SYNC_END_REG_NUM 1
149
150/* Define Offset and Fetch Count Register*/
151
152/* location: {CR13,0,7},{CR35,5,7} */
153#define IGA1_OFFSET_REG_NUM 2
154/* 8 bytes alignment. */
155#define IGA1_OFFSER_ALIGN_BYTE 8
156/* x: H resolution, y: color depth */
157#define IGA1_OFFSET_FORMULA(x, y) ((x*y)/IGA1_OFFSER_ALIGN_BYTE)
158/* location: {SR1C,0,7},{SR1D,0,1} */
159#define IGA1_FETCH_COUNT_REG_NUM 2
160/* 16 bytes alignment. */
161#define IGA1_FETCH_COUNT_ALIGN_BYTE 16
162/* x: H resolution, y: color depth */
163#define IGA1_FETCH_COUNT_PATCH_VALUE 4
164#define IGA1_FETCH_COUNT_FORMULA(x, y) \
165 (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
166
167/* location: {CR66,0,7},{CR67,0,1} */
168#define IGA2_OFFSET_REG_NUM 2
169#define IGA2_OFFSET_ALIGN_BYTE 8
170/* x: H resolution, y: color depth */
171#define IGA2_OFFSET_FORMULA(x, y) ((x*y)/IGA2_OFFSET_ALIGN_BYTE)
172/* location: {CR65,0,7},{CR67,2,3} */
173#define IGA2_FETCH_COUNT_REG_NUM 2
174#define IGA2_FETCH_COUNT_ALIGN_BYTE 16
175#define IGA2_FETCH_COUNT_PATCH_VALUE 0
176#define IGA2_FETCH_COUNT_FORMULA(x, y) \
177 (((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
178
179/* Staring Address*/
180
181/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
182#define IGA1_STARTING_ADDR_REG_NUM 4
183/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
184#define IGA2_STARTING_ADDR_REG_NUM 3
185
186/* Define Display OFFSET*/
187/* These value are by HW suggested value*/
188/* location: {SR17,0,7} */
189#define K800_IGA1_FIFO_MAX_DEPTH 384
190/* location: {SR16,0,5},{SR16,7,7} */
191#define K800_IGA1_FIFO_THRESHOLD 328
192/* location: {SR18,0,5},{SR18,7,7} */
193#define K800_IGA1_FIFO_HIGH_THRESHOLD 296
194/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
195 /* because HW only 5 bits */
196#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
197
198/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
199#define K800_IGA2_FIFO_MAX_DEPTH 384
200/* location: {CR68,0,3},{CR95,4,6} */
201#define K800_IGA2_FIFO_THRESHOLD 328
202/* location: {CR92,0,3},{CR95,0,2} */
203#define K800_IGA2_FIFO_HIGH_THRESHOLD 296
204/* location: {CR94,0,6} */
205#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
206
207/* location: {SR17,0,7} */
208#define P880_IGA1_FIFO_MAX_DEPTH 192
209/* location: {SR16,0,5},{SR16,7,7} */
210#define P880_IGA1_FIFO_THRESHOLD 128
211/* location: {SR18,0,5},{SR18,7,7} */
212#define P880_IGA1_FIFO_HIGH_THRESHOLD 64
213/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
214 /* because HW only 5 bits */
215#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
216
217/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
218#define P880_IGA2_FIFO_MAX_DEPTH 96
219/* location: {CR68,0,3},{CR95,4,6} */
220#define P880_IGA2_FIFO_THRESHOLD 64
221/* location: {CR92,0,3},{CR95,0,2} */
222#define P880_IGA2_FIFO_HIGH_THRESHOLD 32
223/* location: {CR94,0,6} */
224#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
225
226/* VT3314 chipset*/
227
228/* location: {SR17,0,7} */
229#define CN700_IGA1_FIFO_MAX_DEPTH 96
230/* location: {SR16,0,5},{SR16,7,7} */
231#define CN700_IGA1_FIFO_THRESHOLD 80
232/* location: {SR18,0,5},{SR18,7,7} */
233#define CN700_IGA1_FIFO_HIGH_THRESHOLD 64
234/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
235 because HW only 5 bits */
236#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
237/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
238#define CN700_IGA2_FIFO_MAX_DEPTH 96
239/* location: {CR68,0,3},{CR95,4,6} */
240#define CN700_IGA2_FIFO_THRESHOLD 80
241/* location: {CR92,0,3},{CR95,0,2} */
242#define CN700_IGA2_FIFO_HIGH_THRESHOLD 32
243/* location: {CR94,0,6} */
244#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
245
246/* For VT3324, these values are suggested by HW */
247/* location: {SR17,0,7} */
248#define CX700_IGA1_FIFO_MAX_DEPTH 192
249/* location: {SR16,0,5},{SR16,7,7} */
250#define CX700_IGA1_FIFO_THRESHOLD 128
251/* location: {SR18,0,5},{SR18,7,7} */
252#define CX700_IGA1_FIFO_HIGH_THRESHOLD 128
253/* location: {SR22,0,4} */
254#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
255
256/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
257#define CX700_IGA2_FIFO_MAX_DEPTH 96
258/* location: {CR68,0,3},{CR95,4,6} */
259#define CX700_IGA2_FIFO_THRESHOLD 64
260/* location: {CR92,0,3},{CR95,0,2} */
261#define CX700_IGA2_FIFO_HIGH_THRESHOLD 32
262/* location: {CR94,0,6} */
263#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
264
265/* VT3336 chipset*/
266/* location: {SR17,0,7} */
267#define K8M890_IGA1_FIFO_MAX_DEPTH 360
268/* location: {SR16,0,5},{SR16,7,7} */
269#define K8M890_IGA1_FIFO_THRESHOLD 328
270/* location: {SR18,0,5},{SR18,7,7} */
271#define K8M890_IGA1_FIFO_HIGH_THRESHOLD 296
272/* location: {SR22,0,4}. */
273#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
274
275/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
276#define K8M890_IGA2_FIFO_MAX_DEPTH 360
277/* location: {CR68,0,3},{CR95,4,6} */
278#define K8M890_IGA2_FIFO_THRESHOLD 328
279/* location: {CR92,0,3},{CR95,0,2} */
280#define K8M890_IGA2_FIFO_HIGH_THRESHOLD 296
281/* location: {CR94,0,6} */
282#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 124
283
284/* VT3327 chipset*/
285/* location: {SR17,0,7} */
286#define P4M890_IGA1_FIFO_MAX_DEPTH 96
287/* location: {SR16,0,5},{SR16,7,7} */
288#define P4M890_IGA1_FIFO_THRESHOLD 76
289/* location: {SR18,0,5},{SR18,7,7} */
290#define P4M890_IGA1_FIFO_HIGH_THRESHOLD 64
291/* location: {SR22,0,4}. (32/4) =8 */
292#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
293/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
294#define P4M890_IGA2_FIFO_MAX_DEPTH 96
295/* location: {CR68,0,3},{CR95,4,6} */
296#define P4M890_IGA2_FIFO_THRESHOLD 76
297/* location: {CR92,0,3},{CR95,0,2} */
298#define P4M890_IGA2_FIFO_HIGH_THRESHOLD 64
299/* location: {CR94,0,6} */
300#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
301
302/* VT3364 chipset*/
303/* location: {SR17,0,7} */
304#define P4M900_IGA1_FIFO_MAX_DEPTH 96
305/* location: {SR16,0,5},{SR16,7,7} */
306#define P4M900_IGA1_FIFO_THRESHOLD 76
307/* location: {SR18,0,5},{SR18,7,7} */
308#define P4M900_IGA1_FIFO_HIGH_THRESHOLD 76
309/* location: {SR22,0,4}. */
310#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
311/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
312#define P4M900_IGA2_FIFO_MAX_DEPTH 96
313/* location: {CR68,0,3},{CR95,4,6} */
314#define P4M900_IGA2_FIFO_THRESHOLD 76
315/* location: {CR92,0,3},{CR95,0,2} */
316#define P4M900_IGA2_FIFO_HIGH_THRESHOLD 76
317/* location: {CR94,0,6} */
318#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
319
320/* For VT3353, these values are suggested by HW */
321/* location: {SR17,0,7} */
322#define VX800_IGA1_FIFO_MAX_DEPTH 192
323/* location: {SR16,0,5},{SR16,7,7} */
324#define VX800_IGA1_FIFO_THRESHOLD 152
325/* location: {SR18,0,5},{SR18,7,7} */
326#define VX800_IGA1_FIFO_HIGH_THRESHOLD 152
327/* location: {SR22,0,4} */
328#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 64
329/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
330#define VX800_IGA2_FIFO_MAX_DEPTH 96
331/* location: {CR68,0,3},{CR95,4,6} */
332#define VX800_IGA2_FIFO_THRESHOLD 64
333/* location: {CR92,0,3},{CR95,0,2} */
334#define VX800_IGA2_FIFO_HIGH_THRESHOLD 32
335/* location: {CR94,0,6} */
336#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
337
338#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1
339#define IGA1_FIFO_THRESHOLD_REG_NUM 2
340#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2
341#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
342
343#define IGA2_FIFO_DEPTH_SELECT_REG_NUM 3
344#define IGA2_FIFO_THRESHOLD_REG_NUM 2
345#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM 2
346#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
347
348#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x) ((x/2)-1)
349#define IGA1_FIFO_THRESHOLD_FORMULA(x) (x/4)
350#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
351#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
352#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x) (((x/2)/4)-1)
353#define IGA2_FIFO_THRESHOLD_FORMULA(x) (x/4)
354#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
355#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
356
357/************************************************************************/
358/* LCD Timing */
359/************************************************************************/
360
361/* 500 ms = 500000 us */
362#define LCD_POWER_SEQ_TD0 500000
363/* 50 ms = 50000 us */
364#define LCD_POWER_SEQ_TD1 50000
365/* 0 us */
366#define LCD_POWER_SEQ_TD2 0
367/* 210 ms = 210000 us */
368#define LCD_POWER_SEQ_TD3 210000
369/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
370#define CLE266_POWER_SEQ_UNIT 71
371/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
372#define K800_POWER_SEQ_UNIT 142
373/* 2^13 * (1/14.31818M) = 572.1 us */
374#define P880_POWER_SEQ_UNIT 572
375
376#define CLE266_POWER_SEQ_FORMULA(x) ((x)/CLE266_POWER_SEQ_UNIT)
377#define K800_POWER_SEQ_FORMULA(x) ((x)/K800_POWER_SEQ_UNIT)
378#define P880_POWER_SEQ_FORMULA(x) ((x)/P880_POWER_SEQ_UNIT)
379
380/* location: {CR8B,0,7},{CR8F,0,3} */
381#define LCD_POWER_SEQ_TD0_REG_NUM 2
382/* location: {CR8C,0,7},{CR8F,4,7} */
383#define LCD_POWER_SEQ_TD1_REG_NUM 2
384/* location: {CR8D,0,7},{CR90,0,3} */
385#define LCD_POWER_SEQ_TD2_REG_NUM 2
386/* location: {CR8E,0,7},{CR90,4,7} */
387#define LCD_POWER_SEQ_TD3_REG_NUM 2
388
389/* LCD Scaling factor*/
390/* x: indicate setting horizontal size*/
391/* y: indicate panel horizontal size*/
392
393/* Horizontal scaling factor 10 bits (2^10) */
394#define CLE266_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
395/* Vertical scaling factor 10 bits (2^10) */
396#define CLE266_LCD_VER_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
397/* Horizontal scaling factor 10 bits (2^12) */
398#define K800_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*4096)/(y-1))
399/* Vertical scaling factor 10 bits (2^11) */
400#define K800_LCD_VER_SCF_FORMULA(x, y) (((x-1)*2048)/(y-1))
401
402/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
403#define LCD_HOR_SCALING_FACTOR_REG_NUM 3
404/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
405#define LCD_VER_SCALING_FACTOR_REG_NUM 3
406/* location: {CR77,0,7},{CR79,4,5} */
407#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE 2
408/* location: {CR78,0,7},{CR79,6,7} */
409#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
410
411/************************************************
412 ***** Define IGA1 Display Timing *****
413 ************************************************/
414struct io_register {
415 u8 io_addr;
416 u8 start_bit;
417 u8 end_bit;
418};
419
420/* IGA1 Horizontal Total */
421struct iga1_hor_total {
422 int reg_num;
423 struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
424};
425
426/* IGA1 Horizontal Addressable Video */
427struct iga1_hor_addr {
428 int reg_num;
429 struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
430};
431
432/* IGA1 Horizontal Blank Start */
433struct iga1_hor_blank_start {
434 int reg_num;
435 struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
436};
437
438/* IGA1 Horizontal Blank End */
439struct iga1_hor_blank_end {
440 int reg_num;
441 struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
442};
443
444/* IGA1 Horizontal Sync Start */
445struct iga1_hor_sync_start {
446 int reg_num;
447 struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
448};
449
450/* IGA1 Horizontal Sync End */
451struct iga1_hor_sync_end {
452 int reg_num;
453 struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
454};
455
456/* IGA1 Vertical Total */
457struct iga1_ver_total {
458 int reg_num;
459 struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
460};
461
462/* IGA1 Vertical Addressable Video */
463struct iga1_ver_addr {
464 int reg_num;
465 struct io_register reg[IGA1_VER_ADDR_REG_NUM];
466};
467
468/* IGA1 Vertical Blank Start */
469struct iga1_ver_blank_start {
470 int reg_num;
471 struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
472};
473
474/* IGA1 Vertical Blank End */
475struct iga1_ver_blank_end {
476 int reg_num;
477 struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
478};
479
480/* IGA1 Vertical Sync Start */
481struct iga1_ver_sync_start {
482 int reg_num;
483 struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
484};
485
486/* IGA1 Vertical Sync End */
487struct iga1_ver_sync_end {
488 int reg_num;
489 struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
490};
491
492/*****************************************************
493** Define IGA2 Shadow Display Timing ****
494*****************************************************/
495
496/* IGA2 Shadow Horizontal Total */
497struct iga2_shadow_hor_total {
498 int reg_num;
499 struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
500};
501
502/* IGA2 Shadow Horizontal Blank End */
503struct iga2_shadow_hor_blank_end {
504 int reg_num;
505 struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
506};
507
508/* IGA2 Shadow Vertical Total */
509struct iga2_shadow_ver_total {
510 int reg_num;
511 struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
512};
513
514/* IGA2 Shadow Vertical Addressable Video */
515struct iga2_shadow_ver_addr {
516 int reg_num;
517 struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
518};
519
520/* IGA2 Shadow Vertical Blank Start */
521struct iga2_shadow_ver_blank_start {
522 int reg_num;
523 struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
524};
525
526/* IGA2 Shadow Vertical Blank End */
527struct iga2_shadow_ver_blank_end {
528 int reg_num;
529 struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
530};
531
532/* IGA2 Shadow Vertical Sync Start */
533struct iga2_shadow_ver_sync_start {
534 int reg_num;
535 struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
536};
537
538/* IGA2 Shadow Vertical Sync End */
539struct iga2_shadow_ver_sync_end {
540 int reg_num;
541 struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
542};
543
544/*****************************************************
545** Define IGA2 Display Timing ****
546******************************************************/
547
548/* IGA2 Horizontal Total */
549struct iga2_hor_total {
550 int reg_num;
551 struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
552};
553
554/* IGA2 Horizontal Addressable Video */
555struct iga2_hor_addr {
556 int reg_num;
557 struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
558};
559
560/* IGA2 Horizontal Blank Start */
561struct iga2_hor_blank_start {
562 int reg_num;
563 struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
564};
565
566/* IGA2 Horizontal Blank End */
567struct iga2_hor_blank_end {
568 int reg_num;
569 struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
570};
571
572/* IGA2 Horizontal Sync Start */
573struct iga2_hor_sync_start {
574 int reg_num;
575 struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
576};
577
578/* IGA2 Horizontal Sync End */
579struct iga2_hor_sync_end {
580 int reg_num;
581 struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
582};
583
584/* IGA2 Vertical Total */
585struct iga2_ver_total {
586 int reg_num;
587 struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
588};
589
590/* IGA2 Vertical Addressable Video */
591struct iga2_ver_addr {
592 int reg_num;
593 struct io_register reg[IGA2_VER_ADDR_REG_NUM];
594};
595
596/* IGA2 Vertical Blank Start */
597struct iga2_ver_blank_start {
598 int reg_num;
599 struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
600};
601
602/* IGA2 Vertical Blank End */
603struct iga2_ver_blank_end {
604 int reg_num;
605 struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
606};
607
608/* IGA2 Vertical Sync Start */
609struct iga2_ver_sync_start {
610 int reg_num;
611 struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
612};
613
614/* IGA2 Vertical Sync End */
615struct iga2_ver_sync_end {
616 int reg_num;
617 struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
618};
619
620/* IGA1 Offset Register */
621struct iga1_offset {
622 int reg_num;
623 struct io_register reg[IGA1_OFFSET_REG_NUM];
624};
625
626/* IGA2 Offset Register */
627struct iga2_offset {
628 int reg_num;
629 struct io_register reg[IGA2_OFFSET_REG_NUM];
630};
631
632struct offset {
633 struct iga1_offset iga1_offset_reg;
634 struct iga2_offset iga2_offset_reg;
635};
636
637/* IGA1 Fetch Count Register */
638struct iga1_fetch_count {
639 int reg_num;
640 struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
641};
642
643/* IGA2 Fetch Count Register */
644struct iga2_fetch_count {
645 int reg_num;
646 struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
647};
648
649struct fetch_count {
650 struct iga1_fetch_count iga1_fetch_count_reg;
651 struct iga2_fetch_count iga2_fetch_count_reg;
652};
653
654/* Starting Address Register */
655struct iga1_starting_addr {
656 int reg_num;
657 struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
658};
659
660struct iga2_starting_addr {
661 int reg_num;
662 struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
663};
664
665struct starting_addr {
666 struct iga1_starting_addr iga1_starting_addr_reg;
667 struct iga2_starting_addr iga2_starting_addr_reg;
668};
669
670/* LCD Power Sequence Timer */
671struct lcd_pwd_seq_td0 {
672 int reg_num;
673 struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
674};
675
676struct lcd_pwd_seq_td1 {
677 int reg_num;
678 struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
679};
680
681struct lcd_pwd_seq_td2 {
682 int reg_num;
683 struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
684};
685
686struct lcd_pwd_seq_td3 {
687 int reg_num;
688 struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
689};
690
691struct _lcd_pwd_seq_timer {
692 struct lcd_pwd_seq_td0 td0;
693 struct lcd_pwd_seq_td1 td1;
694 struct lcd_pwd_seq_td2 td2;
695 struct lcd_pwd_seq_td3 td3;
696};
697
698/* LCD Scaling Factor */
699struct _lcd_hor_scaling_factor {
700 int reg_num;
701 struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
702};
703
704struct _lcd_ver_scaling_factor {
705 int reg_num;
706 struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
707};
708
709struct _lcd_scaling_factor {
710 struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
711 struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
712};
713
714struct pll_map {
715 u32 clk;
716 u32 cle266_pll;
717 u32 k800_pll;
718 u32 cx700_pll;
719};
720
721struct rgbLUT {
722 u8 red;
723 u8 green;
724 u8 blue;
725};
726
727struct lcd_pwd_seq_timer {
728 u16 td0;
729 u16 td1;
730 u16 td2;
731 u16 td3;
732};
733
734/* Display FIFO Relation Registers*/
735struct iga1_fifo_depth_select {
736 int reg_num;
737 struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
738};
739
740struct iga1_fifo_threshold_select {
741 int reg_num;
742 struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
743};
744
745struct iga1_fifo_high_threshold_select {
746 int reg_num;
747 struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
748};
749
750struct iga1_display_queue_expire_num {
751 int reg_num;
752 struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
753};
754
755struct iga2_fifo_depth_select {
756 int reg_num;
757 struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
758};
759
760struct iga2_fifo_threshold_select {
761 int reg_num;
762 struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
763};
764
765struct iga2_fifo_high_threshold_select {
766 int reg_num;
767 struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
768};
769
770struct iga2_display_queue_expire_num {
771 int reg_num;
772 struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
773};
774
775struct fifo_depth_select {
776 struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
777 struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
778};
779
780struct fifo_threshold_select {
781 struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
782 struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
783};
784
785struct fifo_high_threshold_select {
786 struct iga1_fifo_high_threshold_select
787 iga1_fifo_high_threshold_select_reg;
788 struct iga2_fifo_high_threshold_select
789 iga2_fifo_high_threshold_select_reg;
790};
791
792struct display_queue_expire_num {
793 struct iga1_display_queue_expire_num
794 iga1_display_queue_expire_num_reg;
795 struct iga2_display_queue_expire_num
796 iga2_display_queue_expire_num_reg;
797};
798
799struct iga1_crtc_timing {
800 struct iga1_hor_total hor_total;
801 struct iga1_hor_addr hor_addr;
802 struct iga1_hor_blank_start hor_blank_start;
803 struct iga1_hor_blank_end hor_blank_end;
804 struct iga1_hor_sync_start hor_sync_start;
805 struct iga1_hor_sync_end hor_sync_end;
806 struct iga1_ver_total ver_total;
807 struct iga1_ver_addr ver_addr;
808 struct iga1_ver_blank_start ver_blank_start;
809 struct iga1_ver_blank_end ver_blank_end;
810 struct iga1_ver_sync_start ver_sync_start;
811 struct iga1_ver_sync_end ver_sync_end;
812};
813
814struct iga2_shadow_crtc_timing {
815 struct iga2_shadow_hor_total hor_total_shadow;
816 struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
817 struct iga2_shadow_ver_total ver_total_shadow;
818 struct iga2_shadow_ver_addr ver_addr_shadow;
819 struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
820 struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
821 struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
822 struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
823};
824
825struct iga2_crtc_timing {
826 struct iga2_hor_total hor_total;
827 struct iga2_hor_addr hor_addr;
828 struct iga2_hor_blank_start hor_blank_start;
829 struct iga2_hor_blank_end hor_blank_end;
830 struct iga2_hor_sync_start hor_sync_start;
831 struct iga2_hor_sync_end hor_sync_end;
832 struct iga2_ver_total ver_total;
833 struct iga2_ver_addr ver_addr;
834 struct iga2_ver_blank_start ver_blank_start;
835 struct iga2_ver_blank_end ver_blank_end;
836 struct iga2_ver_sync_start ver_sync_start;
837 struct iga2_ver_sync_end ver_sync_end;
838};
839
840/* device ID */
841#define CLE266 0x3123
842#define KM400 0x3205
843#define CN400_FUNCTION2 0x2259
844#define CN400_FUNCTION3 0x3259
845/* support VT3314 chipset */
846#define CN700_FUNCTION2 0x2314
847#define CN700_FUNCTION3 0x3208
848/* VT3324 chipset */
849#define CX700_FUNCTION2 0x2324
850#define CX700_FUNCTION3 0x3324
851/* VT3204 chipset*/
852#define KM800_FUNCTION3 0x3204
853/* VT3336 chipset*/
854#define KM890_FUNCTION3 0x3336
855/* VT3327 chipset*/
856#define P4M890_FUNCTION3 0x3327
857/* VT3293 chipset*/
858#define CN750_FUNCTION3 0x3208
859/* VT3364 chipset*/
860#define P4M900_FUNCTION3 0x3364
861/* VT3353 chipset*/
862#define VX800_FUNCTION3 0x3353
863
864#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value)
865
866struct IODATA {
867 u8 Index;
868 u8 Mask;
869 u8 Data;
870};
871
872struct pci_device_id_info {
873 u32 vendor;
874 u32 device;
875 u32 chip_index;
876};
877
878extern unsigned int viafb_second_virtual_xres;
879extern unsigned int viafb_second_offset;
880extern int viafb_second_size;
881extern int viafb_SAMM_ON;
882extern int viafb_dual_fb;
883extern int viafb_LCD2_ON;
884extern int viafb_LCD_ON;
885extern int viafb_DVI_ON;
886extern int viafb_accel;
887extern int viafb_hotplug;
888
889void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
890void viafb_set_output_path(int device, int set_iga,
891 int output_interface);
892void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
893 int mode_index, int bpp_byte, int set_iga);
894
895void viafb_set_vclock(u32 CLK, int set_iga);
896void viafb_load_reg(int timing_value, int viafb_load_reg_num,
897 struct io_register *reg,
898 int io_type);
899void viafb_crt_disable(void);
900void viafb_crt_enable(void);
901void init_ad9389(void);
902/* Access I/O Function */
903void viafb_write_reg(u8 index, u16 io_port, u8 data);
904u8 viafb_read_reg(int io_port, u8 index);
905void viafb_lock_crt(void);
906void viafb_unlock_crt(void);
907void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga);
908void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
909void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
910struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
911u32 viafb_get_clk_value(int clk);
912void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
913void viafb_set_color_depth(int bpp_byte, int set_iga);
914void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
915 *p_gfx_dpa_setting);
916
917int viafb_setmode(int vmode_index, int hor_res, int ver_res,
918 int video_bpp, int vmode_index1, int hor_res1,
919 int ver_res1, int video_bpp1);
920void viafb_init_chip_info(void);
921void viafb_init_dac(int set_iga);
922int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
923int viafb_get_refresh(int hres, int vres, u32 float_refresh);
924void viafb_update_device_setting(int hres, int vres, int bpp,
925 int vmode_refresh, int flag);
926void viafb_get_mmio_info(unsigned long *mmio_base,
927 unsigned long *mmio_len);
928
929void viafb_set_iga_path(void);
930void viafb_set_start_addr(void);
931void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
932
933#endif /* __HW_H__ */
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c
new file mode 100644
index 000000000000..1570636c8d51
--- /dev/null
+++ b/drivers/video/via/iface.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24/* Get frame buffer size from VGA BIOS */
25
26unsigned int viafb_get_memsize(void)
27{
28 unsigned int m;
29
30 /* If memory size provided by user */
31 if (viafb_memsize)
32 m = viafb_memsize * Mb;
33 else {
34 m = (unsigned int)viafb_read_reg(VIASR, SR39);
35 m = m * (4 * Mb);
36
37 if ((m < (16 * Mb)) || (m > (64 * Mb)))
38 m = 16 * Mb;
39 }
40 DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb);
41 return m;
42}
43
44/* Get Video Buffer Starting Physical Address(back door)*/
45
46unsigned long viafb_get_videobuf_addr(void)
47{
48 struct pci_dev *pdev = NULL;
49 unsigned char sys_mem;
50 unsigned char video_mem;
51 unsigned long sys_mem_size;
52 unsigned long video_mem_size;
53 /*system memory = 256 MB, video memory 64 MB */
54 unsigned long vmem_starting_adr = 0x0C000000;
55
56 pdev =
57 (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID,
58 VIA_K800_BRIDGE_DID, NULL);
59 if (pdev != NULL) {
60 pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG,
61 &sys_mem);
62 pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG,
63 &video_mem);
64 video_mem = (video_mem & 0x70) >> 4;
65 sys_mem_size = ((unsigned long)sys_mem) << 24;
66 if (video_mem != 0)
67 video_mem_size = (1 << (video_mem)) * 1024 * 1024;
68 else
69 video_mem_size = 0;
70
71 vmem_starting_adr = sys_mem_size - video_mem_size;
72 pci_dev_put(pdev);
73 }
74
75 DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n",
76 vmem_starting_adr);
77 return vmem_starting_adr;
78}
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h
new file mode 100644
index 000000000000..790ec3e3aea2
--- /dev/null
+++ b/drivers/video/via/iface.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __IFACE_H__
23#define __IFACE_H__
24
25#define Kb (1024)
26#define Mb (Kb*Kb)
27
28#define VIA_K800_BRIDGE_VID 0x1106
29#define VIA_K800_BRIDGE_DID 0x3204
30
31#define VIA_K800_SYSTEM_MEMORY_REG 0x47
32#define VIA_K800_VIDEO_MEMORY_REG 0xA1
33
34extern int viafb_memsize;
35unsigned int viafb_get_memsize(void);
36unsigned long viafb_get_videobuf_addr(void);
37
38#endif /* __IFACE_H__ */
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c
new file mode 100644
index 000000000000..da03c074e32a
--- /dev/null
+++ b/drivers/video/via/ioctl.c
@@ -0,0 +1,112 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24int viafb_ioctl_get_viafb_info(u_long arg)
25{
26 struct viafb_ioctl_info viainfo;
27
28 viainfo.viafb_id = VIAID;
29 viainfo.vendor_id = PCI_VIA_VENDOR_ID;
30
31 switch (viaparinfo->chip_info->gfx_chip_name) {
32 case UNICHROME_CLE266:
33 viainfo.device_id = UNICHROME_CLE266_DID;
34 break;
35
36 case UNICHROME_K400:
37 viainfo.device_id = UNICHROME_K400_DID;
38 break;
39
40 case UNICHROME_K800:
41 viainfo.device_id = UNICHROME_K800_DID;
42 break;
43
44 case UNICHROME_PM800:
45 viainfo.device_id = UNICHROME_PM800_DID;
46 break;
47
48 case UNICHROME_CN700:
49 viainfo.device_id = UNICHROME_CN700_DID;
50 break;
51
52 case UNICHROME_CX700:
53 viainfo.device_id = UNICHROME_CX700_DID;
54 break;
55
56 case UNICHROME_K8M890:
57 viainfo.device_id = UNICHROME_K8M890_DID;
58 break;
59
60 case UNICHROME_P4M890:
61 viainfo.device_id = UNICHROME_P4M890_DID;
62 break;
63
64 case UNICHROME_P4M900:
65 viainfo.device_id = UNICHROME_P4M900_DID;
66 break;
67 }
68
69 viainfo.version = VERSION_MAJOR;
70 viainfo.revision = VERSION_MINOR;
71
72 if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
73 return -EFAULT;
74
75 return 0;
76}
77
78/* Hot-Plug Priority: DVI > CRT*/
79int viafb_ioctl_hotplug(int hres, int vres, int bpp)
80{
81 int DVIsense, status = 0;
82 DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
83
84 if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
85 NON_TMDS_TRANSMITTER) {
86 DVIsense = viafb_dvi_sense();
87
88 if (DVIsense) {
89 DEBUG_MSG(KERN_INFO "DVI Attached...\n");
90 if (viafb_DeviceStatus != DVI_Device) {
91 viafb_DVI_ON = 1;
92 viafb_CRT_ON = 0;
93 viafb_LCD_ON = 0;
94 viafb_DeviceStatus = DVI_Device;
95 return viafb_DeviceStatus;
96 }
97 status = 1;
98 } else
99 DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
100 }
101
102 if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
103 viafb_CRT_ON = 1;
104 viafb_DVI_ON = 0;
105 viafb_LCD_ON = 0;
106
107 viafb_DeviceStatus = CRT_Device;
108 return viafb_DeviceStatus;
109 }
110
111 return 0;
112}
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h
new file mode 100644
index 000000000000..842fe30b9868
--- /dev/null
+++ b/drivers/video/via/ioctl.h
@@ -0,0 +1,210 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __IOCTL_H__
23#define __IOCTL_H__
24
25#ifndef __user
26#define __user
27#endif
28
29/* VIAFB IOCTL definition */
30#define VIAFB_GET_INFO_SIZE 0x56494101 /* 'VIA\01' */
31#define VIAFB_GET_INFO 0x56494102 /* 'VIA\02' */
32#define VIAFB_HOTPLUG 0x56494103 /* 'VIA\03' */
33#define VIAFB_SET_HOTPLUG_FLAG 0x56494104 /* 'VIA\04' */
34#define VIAFB_GET_RESOLUTION 0x56494105 /* 'VIA\05' */
35#define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */
36#define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */
37#define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */
38#define VIAFB_SET_DEVICE 0x5649410A
39#define VIAFB_GET_DEVICE 0x5649410B
40#define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */
41#define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */
42#define VIAFB_SET_DEVICE_INFO 0x56494114
43#define VIAFB_GET_DEVICE_INFO 0x56494115
44
45#define VIAFB_GET_DEVICE_SUPPORT 0x56494118
46#define VIAFB_GET_DEVICE_CONNECT 0x56494119
47#define VIAFB_GET_PANEL_SUPPORT_EXPAND 0x5649411A
48#define VIAFB_GET_DRIVER_NAME 0x56494122
49#define VIAFB_GET_DEVICE_SUPPORT_STATE 0x56494123
50#define VIAFB_GET_GAMMA_LUT 0x56494124
51#define VIAFB_SET_GAMMA_LUT 0x56494125
52#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126
53#define VIAFB_SET_VIDEO_DEVICE 0x56494127
54#define VIAFB_GET_VIDEO_DEVICE 0x56494128
55#define VIAFB_SET_SECOND_MODE 0x56494129
56#define VIAFB_SYNC_SURFACE 0x56494130
57#define VIAFB_GET_DRIVER_CAPS 0x56494131
58#define VIAFB_GET_IGA_SCALING_INFO 0x56494132
59#define VIAFB_GET_PANEL_MAX_SIZE 0x56494133
60#define VIAFB_GET_PANEL_MAX_POSITION 0x56494134
61#define VIAFB_SET_PANEL_SIZE 0x56494135
62#define VIAFB_SET_PANEL_POSITION 0x56494136
63#define VIAFB_GET_PANEL_POSITION 0x56494137
64#define VIAFB_GET_PANEL_SIZE 0x56494138
65
66#define None_Device 0x00
67#define CRT_Device 0x01
68#define LCD_Device 0x02
69#define DVI_Device 0x08
70#define CRT2_Device 0x10
71#define LCD2_Device 0x40
72
73#define OP_LCD_CENTERING 0x01
74#define OP_LCD_PANEL_ID 0x02
75#define OP_LCD_MODE 0x03
76
77/*SAMM operation flag*/
78#define OP_SAMM 0x80
79
80#define LCD_PANEL_ID_MAXIMUM 22
81
82#define STATE_ON 0x1
83#define STATE_OFF 0x0
84#define STATE_DEFAULT 0xFFFF
85
86#define MAX_ACTIVE_DEV_NUM 2
87
88struct device_t {
89 unsigned short crt:1;
90 unsigned short dvi:1;
91 unsigned short lcd:1;
92 unsigned short samm:1;
93 unsigned short lcd_dsp_cent:1;
94 unsigned char lcd_mode:1;
95 unsigned short epia_dvi:1;
96 unsigned short lcd_dual_edge:1;
97 unsigned short lcd2:1;
98
99 unsigned short primary_dev;
100 unsigned char lcd_panel_id;
101 unsigned short xres, yres;
102 unsigned short xres1, yres1;
103 unsigned short refresh;
104 unsigned short bpp;
105 unsigned short refresh1;
106 unsigned short bpp1;
107 unsigned short sequence;
108 unsigned short bus_width;
109};
110
111struct viafb_ioctl_info {
112 u32 viafb_id; /* for identifying viafb */
113#define VIAID 0x56494146 /* Identify myself with 'VIAF' */
114 u16 vendor_id;
115 u16 device_id;
116 u8 version;
117 u8 revision;
118 u8 reserved[246]; /* for future use */
119};
120
121struct viafb_ioctl_mode {
122 u32 xres;
123 u32 yres;
124 u32 refresh;
125 u32 bpp;
126 u32 xres_sec;
127 u32 yres_sec;
128 u32 virtual_xres_sec;
129 u32 virtual_yres_sec;
130 u32 refresh_sec;
131 u32 bpp_sec;
132};
133struct viafb_ioctl_samm {
134 u32 samm_status;
135 u32 size_prim;
136 u32 size_sec;
137 u32 mem_base;
138 u32 offset_sec;
139};
140
141struct viafb_driver_version {
142 int iMajorNum;
143 int iKernelNum;
144 int iOSNum;
145 int iMinorNum;
146};
147
148struct viafb_ioctl_lcd_attribute {
149 unsigned int panel_id;
150 unsigned int display_center;
151 unsigned int lcd_mode;
152};
153
154struct viafb_ioctl_setting {
155 /* Enable or disable active devices */
156 unsigned short device_flag;
157 /* Indicate which device should be turn on or turn off. */
158 unsigned short device_status;
159 unsigned int reserved;
160 /* Indicate which LCD's attribute can be changed. */
161 unsigned short lcd_operation_flag;
162 /* 1: SAMM ON 0: SAMM OFF */
163 unsigned short samm_status;
164 /* horizontal resolution of first device */
165 unsigned short first_dev_hor_res;
166 /* vertical resolution of first device */
167 unsigned short first_dev_ver_res;
168 /* horizontal resolution of second device */
169 unsigned short second_dev_hor_res;
170 /* vertical resolution of second device */
171 unsigned short second_dev_ver_res;
172 /* refresh rate of first device */
173 unsigned short first_dev_refresh;
174 /* bpp of first device */
175 unsigned short first_dev_bpp;
176 /* refresh rate of second device */
177 unsigned short second_dev_refresh;
178 /* bpp of second device */
179 unsigned short second_dev_bpp;
180 /* Indicate which device are primary display device. */
181 unsigned int primary_device;
182 /* Indicate which device will show video. only valid in duoview mode */
183 unsigned int video_device_status;
184 unsigned int struct_reserved[34];
185 struct viafb_ioctl_lcd_attribute lcd_attributes;
186};
187
188struct _UTFunctionCaps {
189 unsigned int dw3DScalingState;
190 unsigned int reserved[31];
191};
192
193struct _POSITIONVALUE {
194 unsigned int dwX;
195 unsigned int dwY;
196};
197
198struct _panel_size_pos_info {
199 unsigned int device_type;
200 int x;
201 int y;
202};
203
204extern int viafb_LCD_ON;
205extern int viafb_DVI_ON;
206
207int viafb_ioctl_get_viafb_info(u_long arg);
208int viafb_ioctl_hotplug(int hres, int vres, int bpp);
209
210#endif /* __IOCTL_H__ */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
new file mode 100644
index 000000000000..6c7290a6a447
--- /dev/null
+++ b/drivers/video/via/lcd.c
@@ -0,0 +1,1821 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23#include "lcdtbl.h"
24
25static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = {
26 /* IGA2 Shadow Horizontal Total */
27 {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
28 /* IGA2 Shadow Horizontal Blank End */
29 {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
30 /* IGA2 Shadow Vertical Total */
31 {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
32 /* IGA2 Shadow Vertical Addressable Video */
33 {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
34 /* IGA2 Shadow Vertical Blank Start */
35 {IGA2_SHADOW_VER_BLANK_START_REG_NUM,
36 {{CR72, 0, 7}, {CR74, 4, 6} } },
37 /* IGA2 Shadow Vertical Blank End */
38 {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
39 /* IGA2 Shadow Vertical Sync Start */
40 {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
41 /* IGA2 Shadow Vertical Sync End */
42 {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
43};
44
45static struct _lcd_scaling_factor lcd_scaling_factor = {
46 /* LCD Horizontal Scaling Factor Register */
47 {LCD_HOR_SCALING_FACTOR_REG_NUM,
48 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
49 /* LCD Vertical Scaling Factor Register */
50 {LCD_VER_SCALING_FACTOR_REG_NUM,
51 {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
52};
53static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
54 /* LCD Horizontal Scaling Factor Register */
55 {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
56 /* LCD Vertical Scaling Factor Register */
57 {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
58};
59
60static int check_lvds_chip(int device_id_subaddr, int device_id);
61static bool lvds_identify_integratedlvds(void);
62static int fp_id_to_vindex(int panel_id);
63static int lvds_register_read(int index);
64static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
65 int panel_vres);
66static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
67 int panel_id);
68static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
69 int panel_id);
70static void load_lcd_patch_regs(int set_hres, int set_vres,
71 int panel_id, int set_iga);
72static void via_pitch_alignment_patch_lcd(
73 struct lvds_setting_information *plvds_setting_info,
74 struct lvds_chip_information
75 *plvds_chip_info);
76static void lcd_patch_skew_dvp0(struct lvds_setting_information
77 *plvds_setting_info,
78 struct lvds_chip_information *plvds_chip_info);
79static void lcd_patch_skew_dvp1(struct lvds_setting_information
80 *plvds_setting_info,
81 struct lvds_chip_information *plvds_chip_info);
82static void lcd_patch_skew(struct lvds_setting_information
83 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
84
85static void integrated_lvds_disable(struct lvds_setting_information
86 *plvds_setting_info,
87 struct lvds_chip_information *plvds_chip_info);
88static void integrated_lvds_enable(struct lvds_setting_information
89 *plvds_setting_info,
90 struct lvds_chip_information *plvds_chip_info);
91static void lcd_powersequence_off(void);
92static void lcd_powersequence_on(void);
93static void fill_lcd_format(void);
94static void check_diport_of_integrated_lvds(
95 struct lvds_chip_information *plvds_chip_info,
96 struct lvds_setting_information
97 *plvds_setting_info);
98static struct display_timing lcd_centering_timging(struct display_timing
99 mode_crt_reg,
100 struct display_timing panel_crt_reg);
101static void load_crtc_shadow_timing(struct display_timing mode_timing,
102 struct display_timing panel_timing);
103static void viafb_load_scaling_factor_for_p4m900(int set_hres,
104 int set_vres, int panel_hres, int panel_vres);
105
106static int check_lvds_chip(int device_id_subaddr, int device_id)
107{
108 if (lvds_register_read(device_id_subaddr) == device_id)
109 return OK;
110 else
111 return FAIL;
112}
113
114void viafb_init_lcd_size(void)
115{
116 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
117 DEBUG_MSG(KERN_INFO
118 "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
119 viaparinfo->lvds_setting_info->get_lcd_size_method);
120
121 switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
122 case GET_LCD_SIZE_BY_SYSTEM_BIOS:
123 break;
124 case GET_LCD_SZIE_BY_HW_STRAPPING:
125 break;
126 case GET_LCD_SIZE_BY_VGA_BIOS:
127 DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
128 viaparinfo->lvds_setting_info->lcd_panel_size =
129 fp_id_to_vindex(viafb_lcd_panel_id);
130 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
131 viaparinfo->lvds_setting_info->lcd_panel_id);
132 DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
133 viaparinfo->lvds_setting_info->lcd_panel_size);
134 break;
135 case GET_LCD_SIZE_BY_USER_SETTING:
136 DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
137 viaparinfo->lvds_setting_info->lcd_panel_size =
138 fp_id_to_vindex(viafb_lcd_panel_id);
139 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
140 viaparinfo->lvds_setting_info->lcd_panel_id);
141 DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
142 viaparinfo->lvds_setting_info->lcd_panel_size);
143 break;
144 default:
145 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
146 viaparinfo->lvds_setting_info->lcd_panel_id =
147 LCD_PANEL_ID1_800X600;
148 viaparinfo->lvds_setting_info->lcd_panel_size =
149 fp_id_to_vindex(LCD_PANEL_ID1_800X600);
150 }
151 viaparinfo->lvds_setting_info2->lcd_panel_id =
152 viaparinfo->lvds_setting_info->lcd_panel_id;
153 viaparinfo->lvds_setting_info2->lcd_panel_size =
154 viaparinfo->lvds_setting_info->lcd_panel_size;
155 viaparinfo->lvds_setting_info2->lcd_panel_hres =
156 viaparinfo->lvds_setting_info->lcd_panel_hres;
157 viaparinfo->lvds_setting_info2->lcd_panel_vres =
158 viaparinfo->lvds_setting_info->lcd_panel_vres;
159 viaparinfo->lvds_setting_info2->device_lcd_dualedge =
160 viaparinfo->lvds_setting_info->device_lcd_dualedge;
161 viaparinfo->lvds_setting_info2->LCDDithering =
162 viaparinfo->lvds_setting_info->LCDDithering;
163}
164
165static bool lvds_identify_integratedlvds(void)
166{
167 if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
168 /* Two dual channel LCD (Internal LVDS + External LVDS): */
169 /* If we have an external LVDS, such as VT1636, we should
170 have its chip ID already. */
171 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
172 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
173 INTEGRATED_LVDS;
174 DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\
175 (Internal LVDS + External LVDS)\n");
176 } else {
177 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
178 INTEGRATED_LVDS;
179 DEBUG_MSG(KERN_INFO "Not found external LVDS,\
180 so can't support two dual channel LVDS!\n");
181 }
182 } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
183 /* Two single channel LCD (Internal LVDS + Internal LVDS): */
184 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
185 INTEGRATED_LVDS;
186 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
187 INTEGRATED_LVDS;
188 DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\
189 (Internal LVDS + Internal LVDS)\n");
190 } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
191 /* If we have found external LVDS, just use it,
192 otherwise, we will use internal LVDS as default. */
193 if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
194 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
195 INTEGRATED_LVDS;
196 DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
197 }
198 } else {
199 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
200 NON_LVDS_TRANSMITTER;
201 DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
202 return false;
203 }
204
205 return true;
206}
207
208int viafb_lvds_trasmitter_identify(void)
209{
210 viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX;
211 if (viafb_lvds_identify_vt1636()) {
212 viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
213 DEBUG_MSG(KERN_INFO
214 "Found VIA VT1636 LVDS on port i2c 0x31 \n");
215 } else {
216 viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
217 if (viafb_lvds_identify_vt1636()) {
218 viaparinfo->chip_info->lvds_chip_info.i2c_port =
219 GPIOPORTINDEX;
220 DEBUG_MSG(KERN_INFO
221 "Found VIA VT1636 LVDS on port gpio 0x2c \n");
222 }
223 }
224
225 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
226 lvds_identify_integratedlvds();
227
228 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
229 return true;
230 /* Check for VT1631: */
231 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
232 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
233 VT1631_LVDS_I2C_ADDR;
234
235 if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) {
236 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
237 DEBUG_MSG(KERN_INFO "\n %2d",
238 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
239 DEBUG_MSG(KERN_INFO "\n %2d",
240 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
241 return OK;
242 }
243
244 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
245 NON_LVDS_TRANSMITTER;
246 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
247 VT1631_LVDS_I2C_ADDR;
248 return FAIL;
249}
250
251static int fp_id_to_vindex(int panel_id)
252{
253 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
254
255 if (panel_id > LCD_PANEL_ID_MAXIMUM)
256 viafb_lcd_panel_id = panel_id =
257 viafb_read_reg(VIACR, CR3F) & 0x0F;
258
259 switch (panel_id) {
260 case 0x0:
261 viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
262 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
263 viaparinfo->lvds_setting_info->lcd_panel_id =
264 LCD_PANEL_ID0_640X480;
265 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
266 viaparinfo->lvds_setting_info->LCDDithering = 1;
267 return VIA_RES_640X480;
268 break;
269 case 0x1:
270 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
271 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
272 viaparinfo->lvds_setting_info->lcd_panel_id =
273 LCD_PANEL_ID1_800X600;
274 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
275 viaparinfo->lvds_setting_info->LCDDithering = 1;
276 return VIA_RES_800X600;
277 break;
278 case 0x2:
279 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
280 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
281 viaparinfo->lvds_setting_info->lcd_panel_id =
282 LCD_PANEL_ID2_1024X768;
283 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
284 viaparinfo->lvds_setting_info->LCDDithering = 1;
285 return VIA_RES_1024X768;
286 break;
287 case 0x3:
288 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
289 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
290 viaparinfo->lvds_setting_info->lcd_panel_id =
291 LCD_PANEL_ID3_1280X768;
292 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
293 viaparinfo->lvds_setting_info->LCDDithering = 1;
294 return VIA_RES_1280X768;
295 break;
296 case 0x4:
297 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
298 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
299 viaparinfo->lvds_setting_info->lcd_panel_id =
300 LCD_PANEL_ID4_1280X1024;
301 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
302 viaparinfo->lvds_setting_info->LCDDithering = 1;
303 return VIA_RES_1280X1024;
304 break;
305 case 0x5:
306 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
307 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
308 viaparinfo->lvds_setting_info->lcd_panel_id =
309 LCD_PANEL_ID5_1400X1050;
310 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
311 viaparinfo->lvds_setting_info->LCDDithering = 1;
312 return VIA_RES_1400X1050;
313 break;
314 case 0x6:
315 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
316 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
317 viaparinfo->lvds_setting_info->lcd_panel_id =
318 LCD_PANEL_ID6_1600X1200;
319 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
320 viaparinfo->lvds_setting_info->LCDDithering = 1;
321 return VIA_RES_1600X1200;
322 break;
323 case 0x8:
324 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
325 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
326 viaparinfo->lvds_setting_info->lcd_panel_id =
327 LCD_PANEL_IDA_800X480;
328 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
329 viaparinfo->lvds_setting_info->LCDDithering = 1;
330 return VIA_RES_800X480;
331 break;
332 case 0x9:
333 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
334 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
335 viaparinfo->lvds_setting_info->lcd_panel_id =
336 LCD_PANEL_ID2_1024X768;
337 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
338 viaparinfo->lvds_setting_info->LCDDithering = 1;
339 return VIA_RES_1024X768;
340 break;
341 case 0xA:
342 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
343 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
344 viaparinfo->lvds_setting_info->lcd_panel_id =
345 LCD_PANEL_ID2_1024X768;
346 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
347 viaparinfo->lvds_setting_info->LCDDithering = 0;
348 return VIA_RES_1024X768;
349 break;
350 case 0xB:
351 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
352 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
353 viaparinfo->lvds_setting_info->lcd_panel_id =
354 LCD_PANEL_ID2_1024X768;
355 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
356 viaparinfo->lvds_setting_info->LCDDithering = 0;
357 return VIA_RES_1024X768;
358 break;
359 case 0xC:
360 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
361 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
362 viaparinfo->lvds_setting_info->lcd_panel_id =
363 LCD_PANEL_ID3_1280X768;
364 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
365 viaparinfo->lvds_setting_info->LCDDithering = 0;
366 return VIA_RES_1280X768;
367 break;
368 case 0xD:
369 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
370 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
371 viaparinfo->lvds_setting_info->lcd_panel_id =
372 LCD_PANEL_ID4_1280X1024;
373 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
374 viaparinfo->lvds_setting_info->LCDDithering = 0;
375 return VIA_RES_1280X1024;
376 break;
377 case 0xE:
378 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
379 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
380 viaparinfo->lvds_setting_info->lcd_panel_id =
381 LCD_PANEL_ID5_1400X1050;
382 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
383 viaparinfo->lvds_setting_info->LCDDithering = 0;
384 return VIA_RES_1400X1050;
385 break;
386 case 0xF:
387 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
388 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
389 viaparinfo->lvds_setting_info->lcd_panel_id =
390 LCD_PANEL_ID6_1600X1200;
391 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
392 viaparinfo->lvds_setting_info->LCDDithering = 0;
393 return VIA_RES_1600X1200;
394 break;
395 case 0x10:
396 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
397 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
398 viaparinfo->lvds_setting_info->lcd_panel_id =
399 LCD_PANEL_ID7_1366X768;
400 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
401 viaparinfo->lvds_setting_info->LCDDithering = 0;
402 return VIA_RES_1368X768;
403 break;
404 case 0x11:
405 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
406 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
407 viaparinfo->lvds_setting_info->lcd_panel_id =
408 LCD_PANEL_ID8_1024X600;
409 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
410 viaparinfo->lvds_setting_info->LCDDithering = 1;
411 return VIA_RES_1024X600;
412 break;
413 case 0x12:
414 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
415 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
416 viaparinfo->lvds_setting_info->lcd_panel_id =
417 LCD_PANEL_ID3_1280X768;
418 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
419 viaparinfo->lvds_setting_info->LCDDithering = 1;
420 return VIA_RES_1280X768;
421 break;
422 case 0x13:
423 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
424 viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
425 viaparinfo->lvds_setting_info->lcd_panel_id =
426 LCD_PANEL_ID9_1280X800;
427 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
428 viaparinfo->lvds_setting_info->LCDDithering = 1;
429 return VIA_RES_1280X800;
430 break;
431 case 0x14:
432 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
433 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
434 viaparinfo->lvds_setting_info->lcd_panel_id =
435 LCD_PANEL_IDB_1360X768;
436 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
437 viaparinfo->lvds_setting_info->LCDDithering = 0;
438 return VIA_RES_1360X768;
439 break;
440 case 0x15:
441 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
442 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
443 viaparinfo->lvds_setting_info->lcd_panel_id =
444 LCD_PANEL_ID3_1280X768;
445 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
446 viaparinfo->lvds_setting_info->LCDDithering = 0;
447 return VIA_RES_1280X768;
448 break;
449 case 0x16:
450 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
451 viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
452 viaparinfo->lvds_setting_info->lcd_panel_id =
453 LCD_PANEL_IDC_480X640;
454 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
455 viaparinfo->lvds_setting_info->LCDDithering = 1;
456 return VIA_RES_480X640;
457 break;
458 default:
459 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
460 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
461 viaparinfo->lvds_setting_info->lcd_panel_id =
462 LCD_PANEL_ID1_800X600;
463 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
464 viaparinfo->lvds_setting_info->LCDDithering = 1;
465 return VIA_RES_800X600;
466 }
467}
468
469static int lvds_register_read(int index)
470{
471 u8 data;
472
473 viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
474 viafb_i2c_readbyte((u8) viaparinfo->chip_info->
475 lvds_chip_info.lvds_chip_slave_addr,
476 (u8) index, &data);
477 return data;
478}
479
480static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
481 int panel_vres)
482{
483 int reg_value = 0;
484 int viafb_load_reg_num;
485 struct io_register *reg = NULL;
486
487 DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
488
489 /* LCD Scaling Enable */
490 viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
491 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
492 viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
493 panel_hres, panel_vres);
494 return;
495 }
496
497 /* Check if expansion for horizontal */
498 if (set_hres != panel_hres) {
499 /* Load Horizontal Scaling Factor */
500 switch (viaparinfo->chip_info->gfx_chip_name) {
501 case UNICHROME_CLE266:
502 case UNICHROME_K400:
503 reg_value =
504 CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
505 viafb_load_reg_num =
506 lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
507 reg_num;
508 reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
509 viafb_load_reg(reg_value,
510 viafb_load_reg_num, reg, VIACR);
511 break;
512 case UNICHROME_K800:
513 case UNICHROME_PM800:
514 case UNICHROME_CN700:
515 case UNICHROME_CX700:
516 case UNICHROME_K8M890:
517 case UNICHROME_P4M890:
518 reg_value =
519 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
520 /* Horizontal scaling enabled */
521 viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
522 viafb_load_reg_num =
523 lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
524 reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
525 viafb_load_reg(reg_value,
526 viafb_load_reg_num, reg, VIACR);
527 break;
528 }
529
530 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
531 } else {
532 /* Horizontal scaling disabled */
533 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
534 }
535
536 /* Check if expansion for vertical */
537 if (set_vres != panel_vres) {
538 /* Load Vertical Scaling Factor */
539 switch (viaparinfo->chip_info->gfx_chip_name) {
540 case UNICHROME_CLE266:
541 case UNICHROME_K400:
542 reg_value =
543 CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
544 viafb_load_reg_num =
545 lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
546 reg_num;
547 reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
548 viafb_load_reg(reg_value,
549 viafb_load_reg_num, reg, VIACR);
550 break;
551 case UNICHROME_K800:
552 case UNICHROME_PM800:
553 case UNICHROME_CN700:
554 case UNICHROME_CX700:
555 case UNICHROME_K8M890:
556 case UNICHROME_P4M890:
557 reg_value =
558 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
559 /* Vertical scaling enabled */
560 viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
561 viafb_load_reg_num =
562 lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
563 reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
564 viafb_load_reg(reg_value,
565 viafb_load_reg_num, reg, VIACR);
566 break;
567 }
568
569 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
570 } else {
571 /* Vertical scaling disabled */
572 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
573 }
574}
575
576static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
577 int panel_id)
578{
579 int vmode_index;
580 int reg_num = 0;
581 struct io_reg *lcd_patch_reg = NULL;
582
583 if (viaparinfo->lvds_setting_info->iga_path == IGA2)
584 vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
585 else
586 vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
587 switch (panel_id) {
588 /* LCD 800x600 */
589 case LCD_PANEL_ID1_800X600:
590 switch (vmode_index) {
591 case VIA_RES_640X400:
592 case VIA_RES_640X480:
593 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
594 lcd_patch_reg = K400_LCD_RES_6X4_8X6;
595 break;
596 case VIA_RES_720X480:
597 case VIA_RES_720X576:
598 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
599 lcd_patch_reg = K400_LCD_RES_7X4_8X6;
600 break;
601 }
602 break;
603
604 /* LCD 1024x768 */
605 case LCD_PANEL_ID2_1024X768:
606 switch (vmode_index) {
607 case VIA_RES_640X400:
608 case VIA_RES_640X480:
609 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
610 lcd_patch_reg = K400_LCD_RES_6X4_10X7;
611 break;
612 case VIA_RES_720X480:
613 case VIA_RES_720X576:
614 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
615 lcd_patch_reg = K400_LCD_RES_7X4_10X7;
616 break;
617 case VIA_RES_800X600:
618 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
619 lcd_patch_reg = K400_LCD_RES_8X6_10X7;
620 break;
621 }
622 break;
623
624 /* LCD 1280x1024 */
625 case LCD_PANEL_ID4_1280X1024:
626 switch (vmode_index) {
627 case VIA_RES_640X400:
628 case VIA_RES_640X480:
629 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
630 lcd_patch_reg = K400_LCD_RES_6X4_12X10;
631 break;
632 case VIA_RES_720X480:
633 case VIA_RES_720X576:
634 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
635 lcd_patch_reg = K400_LCD_RES_7X4_12X10;
636 break;
637 case VIA_RES_800X600:
638 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
639 lcd_patch_reg = K400_LCD_RES_8X6_12X10;
640 break;
641 case VIA_RES_1024X768:
642 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
643 lcd_patch_reg = K400_LCD_RES_10X7_12X10;
644 break;
645
646 }
647 break;
648
649 /* LCD 1400x1050 */
650 case LCD_PANEL_ID5_1400X1050:
651 switch (vmode_index) {
652 case VIA_RES_640X480:
653 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
654 lcd_patch_reg = K400_LCD_RES_6X4_14X10;
655 break;
656 case VIA_RES_800X600:
657 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
658 lcd_patch_reg = K400_LCD_RES_8X6_14X10;
659 break;
660 case VIA_RES_1024X768:
661 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
662 lcd_patch_reg = K400_LCD_RES_10X7_14X10;
663 break;
664 case VIA_RES_1280X768:
665 case VIA_RES_1280X800:
666 case VIA_RES_1280X960:
667 case VIA_RES_1280X1024:
668 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
669 lcd_patch_reg = K400_LCD_RES_12X10_14X10;
670 break;
671 }
672 break;
673
674 /* LCD 1600x1200 */
675 case LCD_PANEL_ID6_1600X1200:
676 switch (vmode_index) {
677 case VIA_RES_640X400:
678 case VIA_RES_640X480:
679 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
680 lcd_patch_reg = K400_LCD_RES_6X4_16X12;
681 break;
682 case VIA_RES_720X480:
683 case VIA_RES_720X576:
684 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
685 lcd_patch_reg = K400_LCD_RES_7X4_16X12;
686 break;
687 case VIA_RES_800X600:
688 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
689 lcd_patch_reg = K400_LCD_RES_8X6_16X12;
690 break;
691 case VIA_RES_1024X768:
692 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
693 lcd_patch_reg = K400_LCD_RES_10X7_16X12;
694 break;
695 case VIA_RES_1280X768:
696 case VIA_RES_1280X800:
697 case VIA_RES_1280X960:
698 case VIA_RES_1280X1024:
699 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
700 lcd_patch_reg = K400_LCD_RES_12X10_16X12;
701 break;
702 }
703 break;
704
705 /* LCD 1366x768 */
706 case LCD_PANEL_ID7_1366X768:
707 switch (vmode_index) {
708 case VIA_RES_640X480:
709 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
710 lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
711 break;
712 case VIA_RES_720X480:
713 case VIA_RES_720X576:
714 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
715 lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
716 break;
717 case VIA_RES_800X600:
718 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
719 lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
720 break;
721 case VIA_RES_1024X768:
722 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
723 lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
724 break;
725 case VIA_RES_1280X768:
726 case VIA_RES_1280X800:
727 case VIA_RES_1280X960:
728 case VIA_RES_1280X1024:
729 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
730 lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
731 break;
732 }
733 break;
734
735 /* LCD 1360x768 */
736 case LCD_PANEL_IDB_1360X768:
737 break;
738 }
739 if (reg_num != 0) {
740 /* H.W. Reset : ON */
741 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
742
743 viafb_write_regx(lcd_patch_reg, reg_num);
744
745 /* H.W. Reset : OFF */
746 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
747
748 /* Reset PLL */
749 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
750 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
751
752 /* Fire! */
753 outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
754 }
755}
756
757static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
758 int panel_id)
759{
760 int vmode_index;
761 int reg_num = 0;
762 struct io_reg *lcd_patch_reg = NULL;
763
764 if (viaparinfo->lvds_setting_info->iga_path == IGA2)
765 vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
766 else
767 vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
768
769 switch (panel_id) {
770 case LCD_PANEL_ID5_1400X1050:
771 switch (vmode_index) {
772 case VIA_RES_640X480:
773 reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
774 lcd_patch_reg = P880_LCD_RES_6X4_14X10;
775 break;
776 case VIA_RES_800X600:
777 reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
778 lcd_patch_reg = P880_LCD_RES_8X6_14X10;
779 break;
780 }
781 break;
782 case LCD_PANEL_ID6_1600X1200:
783 switch (vmode_index) {
784 case VIA_RES_640X400:
785 case VIA_RES_640X480:
786 reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
787 lcd_patch_reg = P880_LCD_RES_6X4_16X12;
788 break;
789 case VIA_RES_720X480:
790 case VIA_RES_720X576:
791 reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
792 lcd_patch_reg = P880_LCD_RES_7X4_16X12;
793 break;
794 case VIA_RES_800X600:
795 reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
796 lcd_patch_reg = P880_LCD_RES_8X6_16X12;
797 break;
798 case VIA_RES_1024X768:
799 reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
800 lcd_patch_reg = P880_LCD_RES_10X7_16X12;
801 break;
802 case VIA_RES_1280X768:
803 case VIA_RES_1280X960:
804 case VIA_RES_1280X1024:
805 reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
806 lcd_patch_reg = P880_LCD_RES_12X10_16X12;
807 break;
808 }
809 break;
810
811 }
812 if (reg_num != 0) {
813 /* H.W. Reset : ON */
814 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
815
816 viafb_write_regx(lcd_patch_reg, reg_num);
817
818 /* H.W. Reset : OFF */
819 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
820
821 /* Reset PLL */
822 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
823 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
824
825 /* Fire! */
826 outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
827 }
828}
829
830static void load_lcd_patch_regs(int set_hres, int set_vres,
831 int panel_id, int set_iga)
832{
833 int vmode_index;
834
835 if (viaparinfo->lvds_setting_info->iga_path == IGA2)
836 vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
837 else
838 vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
839
840 viafb_unlock_crt();
841
842 /* Patch for simultaneous & Expansion */
843 if ((set_iga == IGA1_IGA2) &&
844 (viaparinfo->lvds_setting_info->display_method ==
845 LCD_EXPANDSION)) {
846 switch (viaparinfo->chip_info->gfx_chip_name) {
847 case UNICHROME_CLE266:
848 case UNICHROME_K400:
849 load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
850 break;
851 case UNICHROME_K800:
852 break;
853 case UNICHROME_PM800:
854 case UNICHROME_CN700:
855 case UNICHROME_CX700:
856 load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
857 }
858 }
859
860 viafb_lock_crt();
861}
862
863static void via_pitch_alignment_patch_lcd(
864 struct lvds_setting_information *plvds_setting_info,
865 struct lvds_chip_information
866 *plvds_chip_info)
867{
868 unsigned char cr13, cr35, cr65, cr66, cr67;
869 unsigned long dwScreenPitch = 0;
870 unsigned long dwPitch;
871
872 dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
873 if (dwPitch & 0x1F) {
874 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
875 if (plvds_setting_info->iga_path == IGA2) {
876 if (plvds_setting_info->bpp > 8) {
877 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
878 viafb_write_reg(CR66, VIACR, cr66);
879 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
880 cr67 |=
881 (unsigned
882 char)((dwScreenPitch & 0x300) >> 8);
883 viafb_write_reg(CR67, VIACR, cr67);
884 }
885
886 /* Fetch Count */
887 cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
888 cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
889 viafb_write_reg(CR67, VIACR, cr67);
890 cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
891 cr65 += 2;
892 viafb_write_reg(CR65, VIACR, cr65);
893 } else {
894 if (plvds_setting_info->bpp > 8) {
895 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
896 viafb_write_reg(CR13, VIACR, cr13);
897 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
898 cr35 |=
899 (unsigned
900 char)((dwScreenPitch & 0x700) >> 3);
901 viafb_write_reg(CR35, VIACR, cr35);
902 }
903 }
904 }
905}
906static void lcd_patch_skew_dvp0(struct lvds_setting_information
907 *plvds_setting_info,
908 struct lvds_chip_information *plvds_chip_info)
909{
910 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
911 switch (viaparinfo->chip_info->gfx_chip_name) {
912 case UNICHROME_P4M900:
913 viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
914 plvds_chip_info);
915 break;
916 case UNICHROME_P4M890:
917 viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
918 plvds_chip_info);
919 break;
920 }
921 }
922}
923static void lcd_patch_skew_dvp1(struct lvds_setting_information
924 *plvds_setting_info,
925 struct lvds_chip_information *plvds_chip_info)
926{
927 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
928 switch (viaparinfo->chip_info->gfx_chip_name) {
929 case UNICHROME_CX700:
930 viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
931 plvds_chip_info);
932 break;
933 }
934 }
935}
936static void lcd_patch_skew(struct lvds_setting_information
937 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
938{
939 DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
940 switch (plvds_chip_info->output_interface) {
941 case INTERFACE_DVP0:
942 lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
943 break;
944 case INTERFACE_DVP1:
945 lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
946 break;
947 case INTERFACE_DFP_LOW:
948 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
949 viafb_write_reg_mask(CR99, VIACR, 0x08,
950 BIT0 + BIT1 + BIT2 + BIT3);
951 }
952 break;
953 }
954}
955
956/* LCD Set Mode */
957void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
958 struct lvds_setting_information *plvds_setting_info,
959 struct lvds_chip_information *plvds_chip_info)
960{
961 int video_index = plvds_setting_info->lcd_panel_size;
962 int set_iga = plvds_setting_info->iga_path;
963 int mode_bpp = plvds_setting_info->bpp;
964 int viafb_load_reg_num = 0;
965 int reg_value = 0;
966 int set_hres, set_vres;
967 int panel_hres, panel_vres;
968 u32 pll_D_N;
969 int offset;
970 struct io_register *reg = NULL;
971 struct display_timing mode_crt_reg, panel_crt_reg;
972 struct crt_mode_table *panel_crt_table = NULL;
973 struct VideoModeTable *vmode_tbl = NULL;
974
975 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
976 /* Get mode table */
977 mode_crt_reg = mode_crt_table->crtc;
978 /* Get panel table Pointer */
979 vmode_tbl = viafb_get_modetbl_pointer(video_index);
980 panel_crt_table = vmode_tbl->crtc;
981 panel_crt_reg = panel_crt_table->crtc;
982 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
983 set_hres = plvds_setting_info->h_active;
984 set_vres = plvds_setting_info->v_active;
985 panel_hres = plvds_setting_info->lcd_panel_hres;
986 panel_vres = plvds_setting_info->lcd_panel_vres;
987 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
988 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
989 plvds_setting_info->vclk = panel_crt_table->clk;
990 if (set_iga == IGA1) {
991 /* IGA1 doesn't have LCD scaling, so set it as centering. */
992 viafb_load_crtc_timing(lcd_centering_timging
993 (mode_crt_reg, panel_crt_reg), IGA1);
994 } else {
995 /* Expansion */
996 if ((plvds_setting_info->display_method ==
997 LCD_EXPANDSION) & ((set_hres != panel_hres)
998 || (set_vres != panel_vres))) {
999 /* expansion timing IGA2 loaded panel set timing*/
1000 viafb_load_crtc_timing(panel_crt_reg, IGA2);
1001 DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
1002 load_lcd_scaling(set_hres, set_vres, panel_hres,
1003 panel_vres);
1004 DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
1005 } else { /* Centering */
1006 /* centering timing IGA2 always loaded panel
1007 and mode releative timing */
1008 viafb_load_crtc_timing(lcd_centering_timging
1009 (mode_crt_reg, panel_crt_reg), IGA2);
1010 viafb_write_reg_mask(CR79, VIACR, 0x00,
1011 BIT0 + BIT1 + BIT2);
1012 /* LCD scaling disabled */
1013 }
1014 }
1015
1016 if (set_iga == IGA1_IGA2) {
1017 load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
1018 /* Fill shadow registers */
1019
1020 switch (plvds_setting_info->lcd_panel_id) {
1021 case LCD_PANEL_ID0_640X480:
1022 offset = 80;
1023 break;
1024 case LCD_PANEL_ID1_800X600:
1025 case LCD_PANEL_IDA_800X480:
1026 offset = 110;
1027 break;
1028 case LCD_PANEL_ID2_1024X768:
1029 offset = 150;
1030 break;
1031 case LCD_PANEL_ID3_1280X768:
1032 case LCD_PANEL_ID4_1280X1024:
1033 case LCD_PANEL_ID5_1400X1050:
1034 case LCD_PANEL_ID9_1280X800:
1035 offset = 190;
1036 break;
1037 case LCD_PANEL_ID6_1600X1200:
1038 offset = 250;
1039 break;
1040 case LCD_PANEL_ID7_1366X768:
1041 case LCD_PANEL_IDB_1360X768:
1042 offset = 212;
1043 break;
1044 default:
1045 offset = 140;
1046 break;
1047 }
1048
1049 /* Offset for simultaneous */
1050 reg_value = offset;
1051 viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
1052 reg = offset_reg.iga2_offset_reg.reg;
1053 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1054 DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
1055 viafb_load_fetch_count_reg(set_hres, 4, IGA2);
1056 /* Fetch count for simultaneous */
1057 } else { /* SAMM */
1058 /* Offset for IGA2 only */
1059 viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga);
1060 /* Fetch count for IGA2 only */
1061 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
1062
1063 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1064 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1065 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
1066
1067 viafb_set_color_depth(mode_bpp / 8, set_iga);
1068 }
1069
1070 fill_lcd_format();
1071
1072 pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
1073 DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
1074 viafb_set_vclock(pll_D_N, set_iga);
1075
1076 viafb_set_output_path(DEVICE_LCD, set_iga,
1077 plvds_chip_info->output_interface);
1078 lcd_patch_skew(plvds_setting_info, plvds_chip_info);
1079
1080 /* If K8M800, enable LCD Prefetch Mode. */
1081 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
1082 || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
1083 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
1084
1085 load_lcd_patch_regs(set_hres, set_vres,
1086 plvds_setting_info->lcd_panel_id, set_iga);
1087
1088 DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
1089
1090 /* Patch for non 32bit alignment mode */
1091 via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
1092}
1093
1094static void integrated_lvds_disable(struct lvds_setting_information
1095 *plvds_setting_info,
1096 struct lvds_chip_information *plvds_chip_info)
1097{
1098 bool turn_off_first_powersequence = false;
1099 bool turn_off_second_powersequence = false;
1100 if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
1101 turn_off_first_powersequence = true;
1102 if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
1103 turn_off_first_powersequence = true;
1104 if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
1105 turn_off_second_powersequence = true;
1106 if (turn_off_second_powersequence) {
1107 /* Use second power sequence control: */
1108
1109 /* Turn off power sequence. */
1110 viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
1111
1112 /* Turn off back light. */
1113 viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
1114 }
1115 if (turn_off_first_powersequence) {
1116 /* Use first power sequence control: */
1117
1118 /* Turn off power sequence. */
1119 viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
1120
1121 /* Turn off back light. */
1122 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
1123 }
1124
1125 /* Turn DFP High/Low Pad off. */
1126 viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
1127
1128 /* Power off LVDS channel. */
1129 switch (plvds_chip_info->output_interface) {
1130 case INTERFACE_LVDS0:
1131 {
1132 viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
1133 break;
1134 }
1135
1136 case INTERFACE_LVDS1:
1137 {
1138 viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
1139 break;
1140 }
1141
1142 case INTERFACE_LVDS0LVDS1:
1143 {
1144 viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
1145 break;
1146 }
1147 }
1148}
1149
1150static void integrated_lvds_enable(struct lvds_setting_information
1151 *plvds_setting_info,
1152 struct lvds_chip_information *plvds_chip_info)
1153{
1154 bool turn_on_first_powersequence = false;
1155 bool turn_on_second_powersequence = false;
1156
1157 DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
1158 plvds_chip_info->output_interface);
1159 if (plvds_setting_info->lcd_mode == LCD_SPWG)
1160 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
1161 else
1162 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
1163 if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
1164 turn_on_first_powersequence = true;
1165 if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
1166 turn_on_first_powersequence = true;
1167 if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
1168 turn_on_second_powersequence = true;
1169
1170 if (turn_on_second_powersequence) {
1171 /* Use second power sequence control: */
1172
1173 /* Use hardware control power sequence. */
1174 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
1175
1176 /* Turn on back light. */
1177 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
1178
1179 /* Turn on hardware power sequence. */
1180 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
1181 }
1182 if (turn_on_first_powersequence) {
1183 /* Use first power sequence control: */
1184
1185 /* Use hardware control power sequence. */
1186 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
1187
1188 /* Turn on back light. */
1189 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
1190
1191 /* Turn on hardware power sequence. */
1192 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
1193 }
1194
1195 /* Turn DFP High/Low pad on. */
1196 viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
1197
1198 /* Power on LVDS channel. */
1199 switch (plvds_chip_info->output_interface) {
1200 case INTERFACE_LVDS0:
1201 {
1202 viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
1203 break;
1204 }
1205
1206 case INTERFACE_LVDS1:
1207 {
1208 viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
1209 break;
1210 }
1211
1212 case INTERFACE_LVDS0LVDS1:
1213 {
1214 viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
1215 break;
1216 }
1217 }
1218}
1219
1220void viafb_lcd_disable(void)
1221{
1222
1223 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
1224 lcd_powersequence_off();
1225 /* DI1 pad off */
1226 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
1227 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1228 if (viafb_LCD2_ON
1229 && (INTEGRATED_LVDS ==
1230 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
1231 integrated_lvds_disable(viaparinfo->lvds_setting_info,
1232 &viaparinfo->chip_info->lvds_chip_info2);
1233 if (INTEGRATED_LVDS ==
1234 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
1235 integrated_lvds_disable(viaparinfo->lvds_setting_info,
1236 &viaparinfo->chip_info->lvds_chip_info);
1237 if (VT1636_LVDS == viaparinfo->chip_info->
1238 lvds_chip_info.lvds_chip_name)
1239 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
1240 &viaparinfo->chip_info->lvds_chip_info);
1241 } else if (VT1636_LVDS ==
1242 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1243 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
1244 &viaparinfo->chip_info->lvds_chip_info);
1245 } else {
1246 /* DFP-HL pad off */
1247 viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
1248 /* Backlight off */
1249 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
1250 /* 24 bit DI data paht off */
1251 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
1252 /* Simultaneout disabled */
1253 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
1254 }
1255
1256 /* Disable expansion bit */
1257 viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
1258 /* CRT path set to IGA1 */
1259 viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
1260 /* Simultaneout disabled */
1261 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
1262 /* IGA2 path disabled */
1263 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
1264
1265}
1266
1267void viafb_lcd_enable(void)
1268{
1269 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
1270 /* DI1 pad on */
1271 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
1272 lcd_powersequence_on();
1273 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1274 if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
1275 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
1276 integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
1277 &viaparinfo->chip_info->lvds_chip_info2);
1278 if (INTEGRATED_LVDS ==
1279 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
1280 integrated_lvds_enable(viaparinfo->lvds_setting_info,
1281 &viaparinfo->chip_info->lvds_chip_info);
1282 if (VT1636_LVDS == viaparinfo->chip_info->
1283 lvds_chip_info.lvds_chip_name)
1284 viafb_enable_lvds_vt1636(viaparinfo->
1285 lvds_setting_info, &viaparinfo->chip_info->
1286 lvds_chip_info);
1287 } else if (VT1636_LVDS ==
1288 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1289 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
1290 &viaparinfo->chip_info->lvds_chip_info);
1291 } else {
1292 /* DFP-HL pad on */
1293 viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
1294 /* Backlight on */
1295 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
1296 /* 24 bit DI data paht on */
1297 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
1298
1299 /* Set data source selection bit by iga path */
1300 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1301 /* DFP-H set to IGA1 */
1302 viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
1303 /* DFP-L set to IGA1 */
1304 viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
1305 } else {
1306 /* DFP-H set to IGA2 */
1307 viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
1308 /* DFP-L set to IGA2 */
1309 viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
1310 }
1311 /* LCD enabled */
1312 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
1313 }
1314
1315 if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
1316 || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
1317 /* CRT path set to IGA2 */
1318 viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
1319 /* IGA2 path disabled */
1320 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
1321 /* IGA2 path enabled */
1322 } else { /* IGA2 */
1323 viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
1324 }
1325
1326}
1327
1328static void lcd_powersequence_off(void)
1329{
1330 int i, mask, data;
1331
1332 /* Software control power sequence */
1333 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
1334
1335 for (i = 0; i < 3; i++) {
1336 mask = PowerSequenceOff[0][i];
1337 data = PowerSequenceOff[1][i] & mask;
1338 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
1339 udelay(PowerSequenceOff[2][i]);
1340 }
1341
1342 /* Disable LCD */
1343 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
1344}
1345
1346static void lcd_powersequence_on(void)
1347{
1348 int i, mask, data;
1349
1350 /* Software control power sequence */
1351 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
1352
1353 /* Enable LCD */
1354 viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
1355
1356 for (i = 0; i < 3; i++) {
1357 mask = PowerSequenceOn[0][i];
1358 data = PowerSequenceOn[1][i] & mask;
1359 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
1360 udelay(PowerSequenceOn[2][i]);
1361 }
1362
1363 udelay(1);
1364}
1365
1366static void fill_lcd_format(void)
1367{
1368 u8 bdithering = 0, bdual = 0;
1369
1370 if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
1371 bdual = BIT4;
1372 if (viaparinfo->lvds_setting_info->LCDDithering)
1373 bdithering = BIT0;
1374 /* Dual & Dithering */
1375 viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
1376}
1377
1378static void check_diport_of_integrated_lvds(
1379 struct lvds_chip_information *plvds_chip_info,
1380 struct lvds_setting_information
1381 *plvds_setting_info)
1382{
1383 /* Determine LCD DI Port by hardware layout. */
1384 switch (viafb_display_hardware_layout) {
1385 case HW_LAYOUT_LCD_ONLY:
1386 {
1387 if (plvds_setting_info->device_lcd_dualedge) {
1388 plvds_chip_info->output_interface =
1389 INTERFACE_LVDS0LVDS1;
1390 } else {
1391 plvds_chip_info->output_interface =
1392 INTERFACE_LVDS0;
1393 }
1394
1395 break;
1396 }
1397
1398 case HW_LAYOUT_DVI_ONLY:
1399 {
1400 plvds_chip_info->output_interface = INTERFACE_NONE;
1401 break;
1402 }
1403
1404 case HW_LAYOUT_LCD1_LCD2:
1405 case HW_LAYOUT_LCD_EXTERNAL_LCD2:
1406 {
1407 plvds_chip_info->output_interface =
1408 INTERFACE_LVDS0LVDS1;
1409 break;
1410 }
1411
1412 case HW_LAYOUT_LCD_DVI:
1413 {
1414 plvds_chip_info->output_interface = INTERFACE_LVDS1;
1415 break;
1416 }
1417
1418 default:
1419 {
1420 plvds_chip_info->output_interface = INTERFACE_LVDS1;
1421 break;
1422 }
1423 }
1424
1425 DEBUG_MSG(KERN_INFO
1426 "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
1427 viafb_display_hardware_layout,
1428 plvds_chip_info->output_interface);
1429}
1430
1431void viafb_init_lvds_output_interface(struct lvds_chip_information
1432 *plvds_chip_info,
1433 struct lvds_setting_information
1434 *plvds_setting_info)
1435{
1436 if (INTERFACE_NONE != plvds_chip_info->output_interface) {
1437 /*Do nothing, lcd port is specified by module parameter */
1438 return;
1439 }
1440
1441 switch (plvds_chip_info->lvds_chip_name) {
1442
1443 case VT1636_LVDS:
1444 switch (viaparinfo->chip_info->gfx_chip_name) {
1445 case UNICHROME_CX700:
1446 plvds_chip_info->output_interface = INTERFACE_DVP1;
1447 break;
1448 case UNICHROME_CN700:
1449 plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
1450 break;
1451 default:
1452 plvds_chip_info->output_interface = INTERFACE_DVP0;
1453 break;
1454 }
1455 break;
1456
1457 case INTEGRATED_LVDS:
1458 check_diport_of_integrated_lvds(plvds_chip_info,
1459 plvds_setting_info);
1460 break;
1461
1462 default:
1463 switch (viaparinfo->chip_info->gfx_chip_name) {
1464 case UNICHROME_K8M890:
1465 case UNICHROME_P4M900:
1466 case UNICHROME_P4M890:
1467 plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
1468 break;
1469 default:
1470 plvds_chip_info->output_interface = INTERFACE_DFP;
1471 break;
1472 }
1473 break;
1474 }
1475}
1476
1477static struct display_timing lcd_centering_timging(struct display_timing
1478 mode_crt_reg,
1479 struct display_timing panel_crt_reg)
1480{
1481 struct display_timing crt_reg;
1482
1483 crt_reg.hor_total = panel_crt_reg.hor_total;
1484 crt_reg.hor_addr = mode_crt_reg.hor_addr;
1485 crt_reg.hor_blank_start =
1486 (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
1487 crt_reg.hor_addr;
1488 crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
1489 crt_reg.hor_sync_start =
1490 (panel_crt_reg.hor_sync_start -
1491 panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
1492 crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
1493
1494 crt_reg.ver_total = panel_crt_reg.ver_total;
1495 crt_reg.ver_addr = mode_crt_reg.ver_addr;
1496 crt_reg.ver_blank_start =
1497 (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
1498 crt_reg.ver_addr;
1499 crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
1500 crt_reg.ver_sync_start =
1501 (panel_crt_reg.ver_sync_start -
1502 panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
1503 crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
1504
1505 return crt_reg;
1506}
1507
1508static void load_crtc_shadow_timing(struct display_timing mode_timing,
1509 struct display_timing panel_timing)
1510{
1511 struct io_register *reg = NULL;
1512 int i;
1513 int viafb_load_reg_Num = 0;
1514 int reg_value = 0;
1515
1516 if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
1517 /* Expansion */
1518 for (i = 12; i < 20; i++) {
1519 switch (i) {
1520 case H_TOTAL_SHADOW_INDEX:
1521 reg_value =
1522 IGA2_HOR_TOTAL_SHADOW_FORMULA
1523 (panel_timing.hor_total);
1524 viafb_load_reg_Num =
1525 iga2_shadow_crtc_reg.hor_total_shadow.
1526 reg_num;
1527 reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
1528 break;
1529 case H_BLANK_END_SHADOW_INDEX:
1530 reg_value =
1531 IGA2_HOR_BLANK_END_SHADOW_FORMULA
1532 (panel_timing.hor_blank_start,
1533 panel_timing.hor_blank_end);
1534 viafb_load_reg_Num =
1535 iga2_shadow_crtc_reg.
1536 hor_blank_end_shadow.reg_num;
1537 reg =
1538 iga2_shadow_crtc_reg.
1539 hor_blank_end_shadow.reg;
1540 break;
1541 case V_TOTAL_SHADOW_INDEX:
1542 reg_value =
1543 IGA2_VER_TOTAL_SHADOW_FORMULA
1544 (panel_timing.ver_total);
1545 viafb_load_reg_Num =
1546 iga2_shadow_crtc_reg.ver_total_shadow.
1547 reg_num;
1548 reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
1549 break;
1550 case V_ADDR_SHADOW_INDEX:
1551 reg_value =
1552 IGA2_VER_ADDR_SHADOW_FORMULA
1553 (panel_timing.ver_addr);
1554 viafb_load_reg_Num =
1555 iga2_shadow_crtc_reg.ver_addr_shadow.
1556 reg_num;
1557 reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
1558 break;
1559 case V_BLANK_SATRT_SHADOW_INDEX:
1560 reg_value =
1561 IGA2_VER_BLANK_START_SHADOW_FORMULA
1562 (panel_timing.ver_blank_start);
1563 viafb_load_reg_Num =
1564 iga2_shadow_crtc_reg.
1565 ver_blank_start_shadow.reg_num;
1566 reg =
1567 iga2_shadow_crtc_reg.
1568 ver_blank_start_shadow.reg;
1569 break;
1570 case V_BLANK_END_SHADOW_INDEX:
1571 reg_value =
1572 IGA2_VER_BLANK_END_SHADOW_FORMULA
1573 (panel_timing.ver_blank_start,
1574 panel_timing.ver_blank_end);
1575 viafb_load_reg_Num =
1576 iga2_shadow_crtc_reg.
1577 ver_blank_end_shadow.reg_num;
1578 reg =
1579 iga2_shadow_crtc_reg.
1580 ver_blank_end_shadow.reg;
1581 break;
1582 case V_SYNC_SATRT_SHADOW_INDEX:
1583 reg_value =
1584 IGA2_VER_SYNC_START_SHADOW_FORMULA
1585 (panel_timing.ver_sync_start);
1586 viafb_load_reg_Num =
1587 iga2_shadow_crtc_reg.
1588 ver_sync_start_shadow.reg_num;
1589 reg =
1590 iga2_shadow_crtc_reg.
1591 ver_sync_start_shadow.reg;
1592 break;
1593 case V_SYNC_END_SHADOW_INDEX:
1594 reg_value =
1595 IGA2_VER_SYNC_END_SHADOW_FORMULA
1596 (panel_timing.ver_sync_start,
1597 panel_timing.ver_sync_end);
1598 viafb_load_reg_Num =
1599 iga2_shadow_crtc_reg.
1600 ver_sync_end_shadow.reg_num;
1601 reg =
1602 iga2_shadow_crtc_reg.
1603 ver_sync_end_shadow.reg;
1604 break;
1605 }
1606 viafb_load_reg(reg_value,
1607 viafb_load_reg_Num, reg, VIACR);
1608 }
1609 } else { /* Centering */
1610 for (i = 12; i < 20; i++) {
1611 switch (i) {
1612 case H_TOTAL_SHADOW_INDEX:
1613 reg_value =
1614 IGA2_HOR_TOTAL_SHADOW_FORMULA
1615 (panel_timing.hor_total);
1616 viafb_load_reg_Num =
1617 iga2_shadow_crtc_reg.hor_total_shadow.
1618 reg_num;
1619 reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
1620 break;
1621 case H_BLANK_END_SHADOW_INDEX:
1622 reg_value =
1623 IGA2_HOR_BLANK_END_SHADOW_FORMULA
1624 (panel_timing.hor_blank_start,
1625 panel_timing.hor_blank_end);
1626 viafb_load_reg_Num =
1627 iga2_shadow_crtc_reg.
1628 hor_blank_end_shadow.reg_num;
1629 reg =
1630 iga2_shadow_crtc_reg.
1631 hor_blank_end_shadow.reg;
1632 break;
1633 case V_TOTAL_SHADOW_INDEX:
1634 reg_value =
1635 IGA2_VER_TOTAL_SHADOW_FORMULA
1636 (panel_timing.ver_total);
1637 viafb_load_reg_Num =
1638 iga2_shadow_crtc_reg.ver_total_shadow.
1639 reg_num;
1640 reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
1641 break;
1642 case V_ADDR_SHADOW_INDEX:
1643 reg_value =
1644 IGA2_VER_ADDR_SHADOW_FORMULA
1645 (mode_timing.ver_addr);
1646 viafb_load_reg_Num =
1647 iga2_shadow_crtc_reg.ver_addr_shadow.
1648 reg_num;
1649 reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
1650 break;
1651 case V_BLANK_SATRT_SHADOW_INDEX:
1652 reg_value =
1653 IGA2_VER_BLANK_START_SHADOW_FORMULA
1654 (mode_timing.ver_blank_start);
1655 viafb_load_reg_Num =
1656 iga2_shadow_crtc_reg.
1657 ver_blank_start_shadow.reg_num;
1658 reg =
1659 iga2_shadow_crtc_reg.
1660 ver_blank_start_shadow.reg;
1661 break;
1662 case V_BLANK_END_SHADOW_INDEX:
1663 reg_value =
1664 IGA2_VER_BLANK_END_SHADOW_FORMULA
1665 (panel_timing.ver_blank_start,
1666 panel_timing.ver_blank_end);
1667 viafb_load_reg_Num =
1668 iga2_shadow_crtc_reg.
1669 ver_blank_end_shadow.reg_num;
1670 reg =
1671 iga2_shadow_crtc_reg.
1672 ver_blank_end_shadow.reg;
1673 break;
1674 case V_SYNC_SATRT_SHADOW_INDEX:
1675 reg_value =
1676 IGA2_VER_SYNC_START_SHADOW_FORMULA(
1677 (panel_timing.ver_sync_start -
1678 panel_timing.ver_blank_start) +
1679 (panel_timing.ver_addr -
1680 mode_timing.ver_addr) / 2 +
1681 mode_timing.ver_addr);
1682 viafb_load_reg_Num =
1683 iga2_shadow_crtc_reg.ver_sync_start_shadow.
1684 reg_num;
1685 reg =
1686 iga2_shadow_crtc_reg.ver_sync_start_shadow.
1687 reg;
1688 break;
1689 case V_SYNC_END_SHADOW_INDEX:
1690 reg_value =
1691 IGA2_VER_SYNC_END_SHADOW_FORMULA(
1692 (panel_timing.ver_sync_start -
1693 panel_timing.ver_blank_start) +
1694 (panel_timing.ver_addr -
1695 mode_timing.ver_addr) / 2 +
1696 mode_timing.ver_addr,
1697 panel_timing.ver_sync_end);
1698 viafb_load_reg_Num =
1699 iga2_shadow_crtc_reg.ver_sync_end_shadow.
1700 reg_num;
1701 reg =
1702 iga2_shadow_crtc_reg.ver_sync_end_shadow.
1703 reg;
1704 break;
1705 }
1706 viafb_load_reg(reg_value,
1707 viafb_load_reg_Num, reg, VIACR);
1708 }
1709 }
1710}
1711
1712bool viafb_lcd_get_mobile_state(bool *mobile)
1713{
1714 unsigned char *romptr, *tableptr;
1715 u8 core_base;
1716 unsigned char *biosptr;
1717 /* Rom address */
1718 u32 romaddr = 0x000C0000;
1719 u16 start_pattern = 0;
1720
1721 biosptr = ioremap(romaddr, 0x10000);
1722
1723 memcpy(&start_pattern, biosptr, 2);
1724 /* Compare pattern */
1725 if (start_pattern == 0xAA55) {
1726 /* Get the start of Table */
1727 /* 0x1B means BIOS offset position */
1728 romptr = biosptr + 0x1B;
1729 tableptr = biosptr + *((u16 *) romptr);
1730
1731 /* Get the start of biosver structure */
1732 /* 18 means BIOS version position. */
1733 romptr = tableptr + 18;
1734 romptr = biosptr + *((u16 *) romptr);
1735
1736 /* The offset should be 44, but the
1737 actual image is less three char. */
1738 /* pRom += 44; */
1739 romptr += 41;
1740
1741 core_base = *romptr++;
1742
1743 if (core_base & 0x8)
1744 *mobile = false;
1745 else
1746 *mobile = true;
1747 /* release memory */
1748 iounmap(biosptr);
1749
1750 return true;
1751 } else {
1752 iounmap(biosptr);
1753 return false;
1754 }
1755}
1756
1757static void viafb_load_scaling_factor_for_p4m900(int set_hres,
1758 int set_vres, int panel_hres, int panel_vres)
1759{
1760 int h_scaling_factor;
1761 int v_scaling_factor;
1762 u8 cra2 = 0;
1763 u8 cr77 = 0;
1764 u8 cr78 = 0;
1765 u8 cr79 = 0;
1766 u8 cr9f = 0;
1767 /* Check if expansion for horizontal */
1768 if (set_hres < panel_hres) {
1769 /* Load Horizontal Scaling Factor */
1770
1771 /* For VIA_K8M800 or later chipsets. */
1772 h_scaling_factor =
1773 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
1774 /* HSCaleFactor[1:0] at CR9F[1:0] */
1775 cr9f = h_scaling_factor & 0x0003;
1776 /* HSCaleFactor[9:2] at CR77[7:0] */
1777 cr77 = (h_scaling_factor & 0x03FC) >> 2;
1778 /* HSCaleFactor[11:10] at CR79[5:4] */
1779 cr79 = (h_scaling_factor & 0x0C00) >> 10;
1780 cr79 <<= 4;
1781
1782 /* Horizontal scaling enabled */
1783 cra2 = 0xC0;
1784
1785 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
1786 h_scaling_factor);
1787 } else {
1788 /* Horizontal scaling disabled */
1789 cra2 = 0x00;
1790 }
1791
1792 /* Check if expansion for vertical */
1793 if (set_vres < panel_vres) {
1794 /* Load Vertical Scaling Factor */
1795
1796 /* For VIA_K8M800 or later chipsets. */
1797 v_scaling_factor =
1798 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
1799
1800 /* Vertical scaling enabled */
1801 cra2 |= 0x08;
1802 /* VSCaleFactor[0] at CR79[3] */
1803 cr79 |= ((v_scaling_factor & 0x0001) << 3);
1804 /* VSCaleFactor[8:1] at CR78[7:0] */
1805 cr78 |= (v_scaling_factor & 0x01FE) >> 1;
1806 /* VSCaleFactor[10:9] at CR79[7:6] */
1807 cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
1808
1809 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
1810 v_scaling_factor);
1811 } else {
1812 /* Vertical scaling disabled */
1813 cra2 |= 0x00;
1814 }
1815
1816 viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
1817 viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
1818 viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
1819 viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
1820 viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
1821}
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
new file mode 100644
index 000000000000..071f47cf5be1
--- /dev/null
+++ b/drivers/video/via/lcd.h
@@ -0,0 +1,94 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __LCD_H__
22#define __LCD_H__
23
24/*Definition TMDS Device ID register*/
25#define VT1631_DEVICE_ID_REG 0x02
26#define VT1631_DEVICE_ID 0x92
27
28#define VT3271_DEVICE_ID_REG 0x02
29#define VT3271_DEVICE_ID 0x71
30
31#define GET_LCD_SIZE_BY_SYSTEM_BIOS 0x01
32#define GET_LCD_SIZE_BY_VGA_BIOS 0x02
33#define GET_LCD_SZIE_BY_HW_STRAPPING 0x03
34#define GET_LCD_SIZE_BY_USER_SETTING 0x04
35
36/* Definition DVI Panel ID*/
37/* Resolution: 640x480, Channel: single, Dithering: Enable */
38#define LCD_PANEL_ID0_640X480 0x00
39/* Resolution: 800x600, Channel: single, Dithering: Enable */
40#define LCD_PANEL_ID1_800X600 0x01
41/* Resolution: 1024x768, Channel: single, Dithering: Enable */
42#define LCD_PANEL_ID2_1024X768 0x02
43/* Resolution: 1280x768, Channel: single, Dithering: Enable */
44#define LCD_PANEL_ID3_1280X768 0x03
45/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
46#define LCD_PANEL_ID4_1280X1024 0x04
47/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
48#define LCD_PANEL_ID5_1400X1050 0x05
49/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
50#define LCD_PANEL_ID6_1600X1200 0x06
51/* Resolution: 1366x768, Channel: single, Dithering: Disable */
52#define LCD_PANEL_ID7_1366X768 0x07
53/* Resolution: 1024x600, Channel: single, Dithering: Enable*/
54#define LCD_PANEL_ID8_1024X600 0x08
55/* Resolution: 1280x800, Channel: single, Dithering: Enable*/
56#define LCD_PANEL_ID9_1280X800 0x09
57/* Resolution: 800x480, Channel: single, Dithering: Enable*/
58#define LCD_PANEL_IDA_800X480 0x0A
59/* Resolution: 1360x768, Channel: single, Dithering: Disable*/
60#define LCD_PANEL_IDB_1360X768 0x0B
61/* Resolution: 480x640, Channel: single, Dithering: Enable */
62#define LCD_PANEL_IDC_480X640 0x0C
63
64
65extern int viafb_LCD2_ON;
66extern int viafb_LCD_ON;
67extern int viafb_DVI_ON;
68
69void viafb_disable_lvds_vt1636(struct lvds_setting_information
70 *plvds_setting_info,
71 struct lvds_chip_information *plvds_chip_info);
72void viafb_enable_lvds_vt1636(struct lvds_setting_information
73 *plvds_setting_info,
74 struct lvds_chip_information *plvds_chip_info);
75void viafb_lcd_disable(void);
76void viafb_lcd_enable(void);
77void viafb_init_lcd_size(void);
78void viafb_init_lvds_output_interface(struct lvds_chip_information
79 *plvds_chip_info,
80 struct lvds_setting_information
81 *plvds_setting_info);
82void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
83 struct lvds_setting_information *plvds_setting_info,
84 struct lvds_chip_information *plvds_chip_info);
85int viafb_lvds_trasmitter_identify(void);
86void viafb_init_lvds_output_interface(struct lvds_chip_information
87 *plvds_chip_info,
88 struct lvds_setting_information
89 *plvds_setting_info);
90bool viafb_lcd_get_mobile_state(bool *mobile);
91void viafb_load_crtc_timing(struct display_timing device_timing,
92 int set_iga);
93
94#endif /* __LCD_H__ */
diff --git a/drivers/video/via/lcdtbl.h b/drivers/video/via/lcdtbl.h
new file mode 100644
index 000000000000..6f3dd800be59
--- /dev/null
+++ b/drivers/video/via/lcdtbl.h
@@ -0,0 +1,591 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __LCDTBL_H__
22#define __LCDTBL_H__
23
24#include "share.h"
25
26/* CLE266 Software Power Sequence */
27/* {Mask}, {Data}, {Delay} */
28int PowerSequenceOn[3][3] =
29 { {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} };
30int PowerSequenceOff[3][3] =
31 { {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} };
32
33/* ++++++ P880 ++++++ */
34/* Panel 1600x1200 */
35struct io_reg P880_LCD_RES_6X4_16X12[] = {
36 /*IGA2 Horizontal Total */
37 {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
38 /*IGA2 Horizontal Blank End */
39 {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
40 {VIACR, CR5D, 0x40, 0x40},
41 /*IGA2 Horizontal Total Shadow */
42 {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
43 /*IGA2 Horizontal Blank End Shadow */
44 {VIACR, CR6E, 0xFF, 0x5E},
45 /*IGA2 Offset */
46 {VIACR, CR66, 0xFF, 0xD6}, {VIACR, CR67, 0x03, 0x00},
47 /*VCLK*/ {VIASR, SR44, 0xFF, 0x7D}, {VIASR, SR45, 0xFF, 0x8C},
48 {VIASR, SR46, 0xFF, 0x02}
49
50};
51
52#define NUM_TOTAL_P880_LCD_RES_6X4_16X12 ARRAY_SIZE(P880_LCD_RES_6X4_16X12)
53
54struct io_reg P880_LCD_RES_7X4_16X12[] = {
55 /*IGA2 Horizontal Total */
56 {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
57 /*IGA2 Horizontal Blank End */
58 {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
59 {VIACR, CR5D, 0x40, 0x40},
60 /*IGA2 Horizontal Total Shadow */
61 {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
62 /*IGA2 Horizontal Blank End Shadow */
63 {VIACR, CR6E, 0xFF, 0x78},
64 /*IGA2 Offset */
65 {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
66 /*VCLK*/ {VIASR, SR44, 0xFF, 0x78}, {VIASR, SR45, 0xFF, 0x8C},
67 {VIASR, SR46, 0xFF, 0x01}
68
69};
70
71#define NUM_TOTAL_P880_LCD_RES_7X4_16X12 ARRAY_SIZE(P880_LCD_RES_7X4_16X12)
72
73struct io_reg P880_LCD_RES_8X6_16X12[] = {
74 /*IGA2 Horizontal Total */
75 {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
76 /*IGA2 Horizontal Blank End */
77 {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
78 {VIACR, CR5D, 0x40, 0x40},
79 /*IGA2 Horizontal Total Shadow */
80 {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
81 /*IGA2 Horizontal Blank End Shadow */
82 {VIACR, CR6E, 0xFF, 0x83},
83 /*IGA2 Offset */
84 {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
85 /*VCLK*/ {VIASR, SR44, 0xFF, 0x6D}, {VIASR, SR45, 0xFF, 0x88},
86 {VIASR, SR46, 0xFF, 0x03}
87
88};
89
90#define NUM_TOTAL_P880_LCD_RES_8X6_16X12 ARRAY_SIZE(P880_LCD_RES_8X6_16X12)
91
92struct io_reg P880_LCD_RES_10X7_16X12[] = {
93 /*IGA2 Horizontal Total */
94 {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
95 /*IGA2 Horizontal Blank End */
96 {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
97 {VIACR, CR5D, 0x40, 0x40},
98 /*IGA2 Horizontal Total Shadow */
99 {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
100 /*IGA2 Horizontal Blank End Shadow */
101 {VIACR, CR6E, 0xFF, 0xAF},
102 /*IGA2 Offset */
103 {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
104 /*VCLK*/ {VIASR, SR44, 0xFF, 0x92}, {VIASR, SR45, 0xFF, 0x88},
105 {VIASR, SR46, 0xFF, 0x03}
106
107};
108
109#define NUM_TOTAL_P880_LCD_RES_10X7_16X12 ARRAY_SIZE(P880_LCD_RES_10X7_16X12)
110
111struct io_reg P880_LCD_RES_12X10_16X12[] = {
112 /*IGA2 Horizontal Total */
113 {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
114 /*IGA2 Horizontal Blank End */
115 {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
116 {VIACR, CR5D, 0x40, 0x40},
117 /*IGA2 Horizontal Total Shadow */
118 {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
119 /*IGA2 Horizontal Blank End Shadow */
120 {VIACR, CR6E, 0xFF, 0xD4},
121 /*IGA2 Offset */
122 {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
123 /*VCLK*/ {VIASR, SR44, 0xFF, 0xF6}, {VIASR, SR45, 0xFF, 0x88},
124 {VIASR, SR46, 0xFF, 0x05}
125
126};
127
128#define NUM_TOTAL_P880_LCD_RES_12X10_16X12 ARRAY_SIZE(P880_LCD_RES_12X10_16X12)
129
130/* Panel 1400x1050 */
131struct io_reg P880_LCD_RES_6X4_14X10[] = {
132 /* 640x480 */
133 /* IGA2 Horizontal Total */
134 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
135 /* IGA2 Horizontal Blank End */
136 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
137 {VIACR, CR5D, 0x40, 0x24},
138 /* IGA2 Horizontal Total Shadow */
139 {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
140 /* IGA2 Horizontal Blank End Shadow */
141 {VIACR, CR6E, 0xFF, 0x63},
142 /* IGA2 Offset */
143 {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
144 /* VCLK */
145 {VIASR, SR44, 0xFF, 0xC6}, {VIASR, SR45, 0xFF, 0x8C},
146 {VIASR, SR46, 0xFF, 0x05}
147};
148
149#define NUM_TOTAL_P880_LCD_RES_6X4_14X10 ARRAY_SIZE(P880_LCD_RES_6X4_14X10)
150
151struct io_reg P880_LCD_RES_8X6_14X10[] = {
152 /* 800x600 */
153 /* IGA2 Horizontal Total */
154 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
155 /* IGA2 Horizontal Blank End */
156 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
157 {VIACR, CR5D, 0x40, 0x24},
158 /* IGA2 Horizontal Total Shadow */
159 {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
160 /* IGA2 Horizontal Blank End Shadow */
161 {VIACR, CR6E, 0xFF, 0x83},
162 /* IGA2 Offset */
163 {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
164 /* VCLK */
165 {VIASR, SR44, 0xFF, 0x06}, {VIASR, SR45, 0xFF, 0x8D},
166 {VIASR, SR46, 0xFF, 0x05}
167};
168
169#define NUM_TOTAL_P880_LCD_RES_8X6_14X10 ARRAY_SIZE(P880_LCD_RES_8X6_14X10)
170
171/* ++++++ K400 ++++++ */
172/* Panel 1600x1200 */
173struct io_reg K400_LCD_RES_6X4_16X12[] = {
174 /*IGA2 Horizontal Total */
175 {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
176 /*IGA2 Horizontal Blank End */
177 {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
178 {VIACR, CR5D, 0x40, 0x40},
179 /*IGA2 Horizontal Total Shadow */
180 {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
181 /*IGA2 Horizontal Blank End Shadow */
182 {VIACR, CR6E, 0xFF, 0x5E},
183 /*IGA2 Offset */
184 {VIACR, CR66, 0xFF, 0xDA}, {VIACR, CR67, 0x03, 0x00},
185 /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x7F}
186};
187
188#define NUM_TOTAL_K400_LCD_RES_6X4_16X12 ARRAY_SIZE(K400_LCD_RES_6X4_16X12)
189
190struct io_reg K400_LCD_RES_7X4_16X12[] = {
191 /*IGA2 Horizontal Total */
192 {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
193 /*IGA2 Horizontal Blank End */
194 {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
195 {VIACR, CR5D, 0x40, 0x40},
196 /*IGA2 Horizontal Total Shadow */
197 {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
198 /*IGA2 Horizontal Blank End Shadow */
199 {VIACR, CR6E, 0xFF, 0x78},
200 /*IGA2 Offset */
201 {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
202 /*VCLK*/ {VIASR, SR46, 0xFF, 0x46}, {VIASR, SR47, 0xFF, 0x3D}
203};
204
205#define NUM_TOTAL_K400_LCD_RES_7X4_16X12 ARRAY_SIZE(K400_LCD_RES_7X4_16X12)
206
207struct io_reg K400_LCD_RES_8X6_16X12[] = {
208 /*IGA2 Horizontal Total */
209 {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
210 /*IGA2 Horizontal Blank End */
211 {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
212 {VIACR, CR5D, 0x40, 0x40},
213 /*IGA2 Horizontal Total Shadow */
214 {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
215 /*IGA2 Horizontal Blank End Shadow */
216 {VIACR, CR6E, 0xFF, 0x83},
217 /*IGA2 Offset */
218 {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
219 /*VCLK*/ {VIASR, SR46, 0xFF, 0x85}, {VIASR, SR47, 0xFF, 0x6F}
220};
221
222#define NUM_TOTAL_K400_LCD_RES_8X6_16X12 ARRAY_SIZE(K400_LCD_RES_8X6_16X12)
223
224struct io_reg K400_LCD_RES_10X7_16X12[] = {
225 /*IGA2 Horizontal Total */
226 {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
227 /*IGA2 Horizontal Blank End */
228 {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
229 {VIACR, CR5D, 0x40, 0x40},
230 /*IGA2 Horizontal Total Shadow */
231 {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
232 /*IGA2 Horizontal Blank End Shadow */
233 {VIACR, CR6E, 0xFF, 0xAF},
234 /*IGA2 Offset */
235 {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
236 /*VCLK*/ {VIASR, SR46, 0xFF, 0x45}, {VIASR, SR47, 0xFF, 0x4A}
237};
238
239#define NUM_TOTAL_K400_LCD_RES_10X7_16X12 ARRAY_SIZE(K400_LCD_RES_10X7_16X12)
240
241struct io_reg K400_LCD_RES_12X10_16X12[] = {
242 /*IGA2 Horizontal Total */
243 {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
244 /*IGA2 Horizontal Blank End */
245 {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
246 {VIACR, CR5D, 0x40, 0x40},
247 /*IGA2 Horizontal Total Shadow */
248 {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
249 /*IGA2 Horizontal Blank End Shadow */
250 {VIACR, CR6E, 0xFF, 0xD4},
251 /*IGA2 Offset */
252 {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
253 /*VCLK*/ {VIASR, SR46, 0xFF, 0x47}, {VIASR, SR47, 0xFF, 0x7C}
254};
255
256#define NUM_TOTAL_K400_LCD_RES_12X10_16X12 ARRAY_SIZE(K400_LCD_RES_12X10_16X12)
257
258/* Panel 1400x1050 */
259struct io_reg K400_LCD_RES_6X4_14X10[] = {
260 /* 640x400 */
261 /* IGA2 Horizontal Total */
262 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
263 /* IGA2 Horizontal Blank End */
264 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
265 {VIACR, CR5D, 0x40, 0x24},
266 /* IGA2 Horizontal Total Shadow */
267 {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
268 /* IGA2 Horizontal Blank End Shadow */
269 {VIACR, CR6E, 0xFF, 0x63},
270 /* IGA2 Offset */
271 {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
272 /* VCLK */
273 {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
274};
275
276#define NUM_TOTAL_K400_LCD_RES_6X4_14X10 ARRAY_SIZE(K400_LCD_RES_6X4_14X10)
277
278struct io_reg K400_LCD_RES_8X6_14X10[] = {
279 /* 800x600 */
280 /* IGA2 Horizontal Total */
281 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
282 /* IGA2 Horizontal Blank End */
283 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
284 {VIACR, CR5D, 0x40, 0x24},
285 /* IGA2 Horizontal Total Shadow */
286 {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
287 /* IGA2 Horizontal Blank End Shadow */
288 {VIACR, CR6E, 0xFF, 0x83},
289 /* IGA2 Offset */
290 {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
291 /* VCLK */
292 {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
293};
294
295#define NUM_TOTAL_K400_LCD_RES_8X6_14X10 ARRAY_SIZE(K400_LCD_RES_8X6_14X10)
296
297struct io_reg K400_LCD_RES_10X7_14X10[] = {
298 /* 1024x768 */
299 /* IGA2 Horizontal Total */
300 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
301 /* IGA2 Horizontal Blank End */
302 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
303 {VIACR, CR5D, 0x40, 0x24},
304 /* IGA2 Horizontal Total Shadow */
305 {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
306 /* IGA2 Horizontal Blank End Shadow */
307 {VIACR, CR6E, 0xFF, 0xA7},
308 /* IGA2 Offset */
309 {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
310 /* VCLK */
311 {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
312};
313
314#define NUM_TOTAL_K400_LCD_RES_10X7_14X10 ARRAY_SIZE(K400_LCD_RES_10X7_14X10)
315
316struct io_reg K400_LCD_RES_12X10_14X10[] = {
317 /* 1280x768, 1280x960, 1280x1024 */
318 /* IGA2 Horizontal Total */
319 {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
320 /* IGA2 Horizontal Blank End */
321 {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
322 {VIACR, CR5D, 0x40, 0x24},
323 /* IGA2 Horizontal Total Shadow */
324 {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
325 /* IGA2 Horizontal Blank End Shadow */
326 {VIACR, CR6E, 0xFF, 0xD2},
327 /* IGA2 Offset */
328 {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
329 /* VCLK */
330 {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
331};
332
333#define NUM_TOTAL_K400_LCD_RES_12X10_14X10 ARRAY_SIZE(K400_LCD_RES_12X10_14X10)
334
335/* ++++++ K400 ++++++ */
336/* Panel 1366x768 */
337struct io_reg K400_LCD_RES_6X4_1366X7[] = {
338 /* 640x400 */
339 /* IGA2 Horizontal Total */
340 {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
341 /* IGA2 Horizontal Blank End */
342 {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
343 {VIACR, CR5D, 0x40, 0x13},
344 /* IGA2 Horizontal Total Shadow */
345 {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
346 /* IGA2 Horizontal Blank End Shadow */
347 {VIACR, CR6E, 0xFF, 0x64},
348 /* IGA2 Offset */
349 {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
350 /* VCLK */
351 {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
352};
353
354#define NUM_TOTAL_K400_LCD_RES_6X4_1366X7 ARRAY_SIZE(K400_LCD_RES_6X4_1366X7)
355
356struct io_reg K400_LCD_RES_7X4_1366X7[] = {
357 /* IGA2 Horizontal Total */
358 {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
359 /* IGA2 Horizontal Blank End */
360 {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
361 {VIACR, CR5D, 0x40, 0x13},
362 /* IGA2 Horizontal Total Shadow */
363 {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
364 /* IGA2 Horizontal Blank End Shadow */
365 {VIACR, CR6E, 0xFF, 0x75},
366 /* IGA2 Offset */
367 {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
368 /* VCLK */
369 {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
370};
371
372#define NUM_TOTAL_K400_LCD_RES_7X4_1366X7 ARRAY_SIZE(K400_LCD_RES_7X4_1366X7)
373
374struct io_reg K400_LCD_RES_8X6_1366X7[] = {
375 /* 800x600 */
376 /* IGA2 Horizontal Total */
377 {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
378 /* IGA2 Horizontal Blank End */
379 {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
380 {VIACR, CR5D, 0x40, 0x13},
381 /* IGA2 Horizontal Total Shadow */
382 {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
383 /* IGA2 Horizontal Blank End Shadow */
384 {VIACR, CR6E, 0xFF, 0x82},
385 /* IGA2 Offset */
386 {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
387 /* VCLK */
388 {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
389};
390
391#define NUM_TOTAL_K400_LCD_RES_8X6_1366X7 ARRAY_SIZE(K400_LCD_RES_8X6_1366X7)
392
393struct io_reg K400_LCD_RES_10X7_1366X7[] = {
394 /* 1024x768 */
395 /* IGA2 Horizontal Total */
396 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
397 /* IGA2 Horizontal Blank End */
398 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
399 {VIACR, CR5D, 0x40, 0x24},
400 /* IGA2 Horizontal Total Shadow */
401 {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
402 /* IGA2 Horizontal Blank End Shadow */
403 {VIACR, CR6E, 0xFF, 0xA7},
404 /* IGA2 Offset */
405 {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
406 /* VCLK */
407 {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
408};
409
410#define NUM_TOTAL_K400_LCD_RES_10X7_1366X7 ARRAY_SIZE(K400_LCD_RES_10X7_1366X7)
411
412struct io_reg K400_LCD_RES_12X10_1366X7[] = {
413 /* 1280x768, 1280x960, 1280x1024 */
414 /* IGA2 Horizontal Total */
415 {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
416 /* IGA2 Horizontal Blank End */
417 {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
418 {VIACR, CR5D, 0x40, 0x24},
419 /* IGA2 Horizontal Total Shadow */
420 {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
421 /* IGA2 Horizontal Blank End Shadow */
422 {VIACR, CR6E, 0xFF, 0xD2},
423 /* IGA2 Offset */
424 {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
425 /* VCLK */
426 {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
427};
428
429#define NUM_TOTAL_K400_LCD_RES_12X10_1366X7\
430 ARRAY_SIZE(K400_LCD_RES_12X10_1366X7)
431
432/* ++++++ K400 ++++++ */
433/* Panel 1280x1024 */
434struct io_reg K400_LCD_RES_6X4_12X10[] = {
435 /*IGA2 Horizontal Total */
436 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
437 /*IGA2 Horizontal Blank End */
438 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
439 {VIACR, CR5D, 0x40, 0x1C},
440 /*IGA2 Horizontal Total Shadow */
441 {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x34},
442 /*IGA2 Horizontal Blank End Shadow */
443 {VIACR, CR6E, 0xFF, 0x63},
444 /*IGA2 Offset */
445 {VIACR, CR66, 0xFF, 0xAA}, {VIACR, CR67, 0x03, 0x00},
446 /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
447};
448
449#define NUM_TOTAL_K400_LCD_RES_6X4_12X10 ARRAY_SIZE(K400_LCD_RES_6X4_12X10)
450
451struct io_reg K400_LCD_RES_7X4_12X10[] = {
452 /*IGA2 Horizontal Total */
453 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
454 /*IGA2 Horizontal Blank End */
455 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
456 {VIACR, CR5D, 0x40, 0x1C},
457 /*IGA2 Horizontal Total Shadow */
458 {VIACR, CR6D, 0xFF, 0x68}, {VIACR, CR71, 0x08, 0x34},
459 /*IGA2 Horizontal Blank End Shadow */
460 {VIACR, CR6E, 0xFF, 0x6C},
461 /*IGA2 Offset */
462 {VIACR, CR66, 0xFF, 0xA8}, {VIACR, CR67, 0x03, 0x00},
463 /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0xED}
464};
465
466#define NUM_TOTAL_K400_LCD_RES_7X4_12X10 ARRAY_SIZE(K400_LCD_RES_7X4_12X10)
467
468struct io_reg K400_LCD_RES_8X6_12X10[] = {
469 /*IGA2 Horizontal Total */
470 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
471 /*IGA2 Horizontal Blank End */
472 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
473 {VIACR, CR5D, 0x40, 0x1C},
474 /*IGA2 Horizontal Total Shadow */
475 {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x34},
476 /*IGA2 Horizontal Blank End Shadow */
477 {VIACR, CR6E, 0xFF, 0x83},
478 /*IGA2 Offset */
479 {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
480 /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
481};
482
483#define NUM_TOTAL_K400_LCD_RES_8X6_12X10 ARRAY_SIZE(K400_LCD_RES_8X6_12X10)
484
485struct io_reg K400_LCD_RES_10X7_12X10[] = {
486 /*IGA2 Horizontal Total */
487 {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
488 /*IGA2 Horizontal Blank End */
489 {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
490 {VIACR, CR5D, 0x40, 0x1C},
491 /*IGA2 Horizontal Total Shadow */
492 {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x34},
493 /*IGA2 Horizontal Blank End Shadow */
494 {VIACR, CR6E, 0xFF, 0xA7},
495 /*IGA2 Offset */
496 {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x04},
497 /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
498};
499
500#define NUM_TOTAL_K400_LCD_RES_10X7_12X10 ARRAY_SIZE(K400_LCD_RES_10X7_12X10)
501
502/* ++++++ K400 ++++++ */
503/* Panel 1024x768 */
504struct io_reg K400_LCD_RES_6X4_10X7[] = {
505 /*IGA2 Horizontal Total */
506 {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
507 /*IGA2 Horizontal Blank End */
508 {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
509 {VIACR, CR5D, 0x40, 0x13},
510 /*IGA2 Horizontal Total Shadow */
511 {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
512 /*IGA2 Horizontal Blank End Shadow */
513 {VIACR, CR6E, 0xFF, 0x64},
514 /*IGA2 Offset */
515 {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
516 /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
517};
518
519#define NUM_TOTAL_K400_LCD_RES_6X4_10X7 ARRAY_SIZE(K400_LCD_RES_6X4_10X7)
520
521struct io_reg K400_LCD_RES_7X4_10X7[] = {
522 /*IGA2 Horizontal Total */
523 {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
524 /*IGA2 Horizontal Blank End */
525 {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
526 {VIACR, CR5D, 0x40, 0x13},
527 /*IGA2 Horizontal Total Shadow */
528 {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
529 /*IGA2 Horizontal Blank End Shadow */
530 {VIACR, CR6E, 0xFF, 0x75},
531 /*IGA2 Offset */
532 {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
533 /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
534};
535
536#define NUM_TOTAL_K400_LCD_RES_7X4_10X7 ARRAY_SIZE(K400_LCD_RES_7X4_10X7)
537
538struct io_reg K400_LCD_RES_8X6_10X7[] = {
539 /*IGA2 Horizontal Total */
540 {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
541 /*IGA2 Horizontal Blank End */
542 {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
543 {VIACR, CR5D, 0x40, 0x13},
544 /*IGA2 Horizontal Total Shadow */
545 {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
546 /*IGA2 Horizontal Blank End Shadow */
547 {VIACR, CR6E, 0xFF, 0x82},
548 /*IGA2 Offset */
549 {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
550 /*VCLK*/ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
551};
552
553#define NUM_TOTAL_K400_LCD_RES_8X6_10X7 ARRAY_SIZE(K400_LCD_RES_8X6_10X7)
554
555/* ++++++ K400 ++++++ */
556/* Panel 800x600 */
557struct io_reg K400_LCD_RES_6X4_8X6[] = {
558 /*IGA2 Horizontal Total */
559 {VIACR, CR50, 0xFF, 0x1A}, {VIACR, CR55, 0x0F, 0x34},
560 /*IGA2 Horizontal Blank End */
561 {VIACR, CR53, 0xFF, 0x1A}, {VIACR, CR54, 0x38, 0xE3},
562 {VIACR, CR5D, 0x40, 0x12},
563 /*IGA2 Horizontal Total Shadow */
564 {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x22},
565 /*IGA2 Horizontal Blank End Shadow */
566 {VIACR, CR6E, 0xFF, 0x63},
567 /*IGA2 Offset */
568 {VIACR, CR66, 0xFF, 0x6E}, {VIACR, CR67, 0x03, 0x00},
569 /*VCLK*/ {VIASR, SR46, 0xFF, 0x86}, {VIASR, SR47, 0xFF, 0xB3}
570};
571
572#define NUM_TOTAL_K400_LCD_RES_6X4_8X6 ARRAY_SIZE(K400_LCD_RES_6X4_8X6)
573
574struct io_reg K400_LCD_RES_7X4_8X6[] = {
575 /*IGA2 Horizontal Total */
576 {VIACR, CR50, 0xFF, 0x1F}, {VIACR, CR55, 0x0F, 0x34},
577 /*IGA2 Horizontal Blank End */
578 {VIACR, CR53, 0xFF, 0x1F}, {VIACR, CR54, 0x38, 0xE3},
579 {VIACR, CR5D, 0x40, 0x12},
580 /*IGA2 Horizontal Total Shadow */
581 {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x22},
582 /*IGA2 Horizontal Blank End Shadow */
583 {VIACR, CR6E, 0xFF, 0x83},
584 /*IGA2 Offset */
585 {VIACR, CR66, 0xFF, 0x78}, {VIACR, CR67, 0x03, 0x00},
586 /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x59}
587};
588
589#define NUM_TOTAL_K400_LCD_RES_7X4_8X6 ARRAY_SIZE(K400_LCD_RES_7X4_8X6)
590
591#endif /* __LCDTBL_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
new file mode 100644
index 000000000000..2e1254da9c8c
--- /dev/null
+++ b/drivers/video/via/share.h
@@ -0,0 +1,1105 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __SHARE_H__
23#define __SHARE_H__
24
25/* Define Return Value */
26#define FAIL -1
27#define OK 1
28
29#ifndef NULL
30#define NULL 0
31#endif
32
33/* Define Bit Field */
34#define BIT0 0x01
35#define BIT1 0x02
36#define BIT2 0x04
37#define BIT3 0x08
38#define BIT4 0x10
39#define BIT5 0x20
40#define BIT6 0x40
41#define BIT7 0x80
42
43/* Video Memory Size */
44#define VIDEO_MEMORY_SIZE_16M 0x1000000
45
46/* Definition Mode Index
47*/
48#define VIA_RES_640X480 0
49#define VIA_RES_800X600 1
50#define VIA_RES_1024X768 2
51#define VIA_RES_1152X864 3
52#define VIA_RES_1280X1024 4
53#define VIA_RES_1600X1200 5
54#define VIA_RES_1440X1050 6
55#define VIA_RES_1280X768 7
56#define VIA_RES_1280X960 8
57#define VIA_RES_1920X1440 9
58#define VIA_RES_848X480 10
59#define VIA_RES_1400X1050 11
60#define VIA_RES_720X480 12
61#define VIA_RES_720X576 13
62#define VIA_RES_1024X512 14
63#define VIA_RES_856X480 15
64#define VIA_RES_1024X576 16
65#define VIA_RES_640X400 17
66#define VIA_RES_1280X720 18
67#define VIA_RES_1920X1080 19
68#define VIA_RES_800X480 20
69#define VIA_RES_1368X768 21
70#define VIA_RES_1024X600 22
71#define VIA_RES_1280X800 23
72#define VIA_RES_1680X1050 24
73#define VIA_RES_960X600 25
74#define VIA_RES_1000X600 26
75#define VIA_RES_1088X612 27
76#define VIA_RES_1152X720 28
77#define VIA_RES_1200X720 29
78#define VIA_RES_1280X600 30
79#define VIA_RES_1360X768 31
80#define VIA_RES_1366X768 32
81#define VIA_RES_1440X900 33
82#define VIA_RES_1600X900 34
83#define VIA_RES_1600X1024 35
84#define VIA_RES_1792X1344 36
85#define VIA_RES_1856X1392 37
86#define VIA_RES_1920X1200 38
87#define VIA_RES_2048X1536 39
88#define VIA_RES_480X640 40
89
90/*Reduce Blanking*/
91#define VIA_RES_1360X768_RB 131
92#define VIA_RES_1440X900_RB 133
93#define VIA_RES_1400X1050_RB 111
94#define VIA_RES_1600X900_RB 134
95#define VIA_RES_1680X1050_RB 124
96#define VIA_RES_1920X1080_RB 119
97#define VIA_RES_1920X1200_RB 138
98
99#define VIA_RES_INVALID 255
100
101/* standard VGA IO port
102*/
103#define VIARMisc 0x3CC
104#define VIAWMisc 0x3C2
105#define VIAStatus 0x3DA
106#define VIACR 0x3D4
107#define VIASR 0x3C4
108#define VIAGR 0x3CE
109#define VIAAR 0x3C0
110
111#define StdCR 0x19
112#define StdSR 0x04
113#define StdGR 0x09
114#define StdAR 0x14
115
116#define PatchCR 11
117
118/* Display path */
119#define IGA1 1
120#define IGA2 2
121#define IGA1_IGA2 3
122
123/* Define Color Depth */
124#define MODE_8BPP 1
125#define MODE_16BPP 2
126#define MODE_32BPP 4
127
128#define GR20 0x20
129#define GR21 0x21
130#define GR22 0x22
131
132/* Sequencer Registers */
133#define SR01 0x01
134#define SR10 0x10
135#define SR12 0x12
136#define SR15 0x15
137#define SR16 0x16
138#define SR17 0x17
139#define SR18 0x18
140#define SR1B 0x1B
141#define SR1A 0x1A
142#define SR1C 0x1C
143#define SR1D 0x1D
144#define SR1E 0x1E
145#define SR1F 0x1F
146#define SR20 0x20
147#define SR21 0x21
148#define SR22 0x22
149#define SR2A 0x2A
150#define SR2D 0x2D
151#define SR2E 0x2E
152
153#define SR30 0x30
154#define SR39 0x39
155#define SR3D 0x3D
156#define SR3E 0x3E
157#define SR3F 0x3F
158#define SR40 0x40
159#define SR43 0x43
160#define SR44 0x44
161#define SR45 0x45
162#define SR46 0x46
163#define SR47 0x47
164#define SR48 0x48
165#define SR49 0x49
166#define SR4A 0x4A
167#define SR4B 0x4B
168#define SR4C 0x4C
169#define SR52 0x52
170#define SR5E 0x5E
171#define SR65 0x65
172
173/* CRT Controller Registers */
174#define CR00 0x00
175#define CR01 0x01
176#define CR02 0x02
177#define CR03 0x03
178#define CR04 0x04
179#define CR05 0x05
180#define CR06 0x06
181#define CR07 0x07
182#define CR08 0x08
183#define CR09 0x09
184#define CR0A 0x0A
185#define CR0B 0x0B
186#define CR0C 0x0C
187#define CR0D 0x0D
188#define CR0E 0x0E
189#define CR0F 0x0F
190#define CR10 0x10
191#define CR11 0x11
192#define CR12 0x12
193#define CR13 0x13
194#define CR14 0x14
195#define CR15 0x15
196#define CR16 0x16
197#define CR17 0x17
198#define CR18 0x18
199
200/* Extend CRT Controller Registers */
201#define CR30 0x30
202#define CR31 0x31
203#define CR32 0x32
204#define CR33 0x33
205#define CR34 0x34
206#define CR35 0x35
207#define CR36 0x36
208#define CR37 0x37
209#define CR38 0x38
210#define CR39 0x39
211#define CR3A 0x3A
212#define CR3B 0x3B
213#define CR3C 0x3C
214#define CR3D 0x3D
215#define CR3E 0x3E
216#define CR3F 0x3F
217#define CR40 0x40
218#define CR41 0x41
219#define CR42 0x42
220#define CR43 0x43
221#define CR44 0x44
222#define CR45 0x45
223#define CR46 0x46
224#define CR47 0x47
225#define CR48 0x48
226#define CR49 0x49
227#define CR4A 0x4A
228#define CR4B 0x4B
229#define CR4C 0x4C
230#define CR4D 0x4D
231#define CR4E 0x4E
232#define CR4F 0x4F
233#define CR50 0x50
234#define CR51 0x51
235#define CR52 0x52
236#define CR53 0x53
237#define CR54 0x54
238#define CR55 0x55
239#define CR56 0x56
240#define CR57 0x57
241#define CR58 0x58
242#define CR59 0x59
243#define CR5A 0x5A
244#define CR5B 0x5B
245#define CR5C 0x5C
246#define CR5D 0x5D
247#define CR5E 0x5E
248#define CR5F 0x5F
249#define CR60 0x60
250#define CR61 0x61
251#define CR62 0x62
252#define CR63 0x63
253#define CR64 0x64
254#define CR65 0x65
255#define CR66 0x66
256#define CR67 0x67
257#define CR68 0x68
258#define CR69 0x69
259#define CR6A 0x6A
260#define CR6B 0x6B
261#define CR6C 0x6C
262#define CR6D 0x6D
263#define CR6E 0x6E
264#define CR6F 0x6F
265#define CR70 0x70
266#define CR71 0x71
267#define CR72 0x72
268#define CR73 0x73
269#define CR74 0x74
270#define CR75 0x75
271#define CR76 0x76
272#define CR77 0x77
273#define CR78 0x78
274#define CR79 0x79
275#define CR7A 0x7A
276#define CR7B 0x7B
277#define CR7C 0x7C
278#define CR7D 0x7D
279#define CR7E 0x7E
280#define CR7F 0x7F
281#define CR80 0x80
282#define CR81 0x81
283#define CR82 0x82
284#define CR83 0x83
285#define CR84 0x84
286#define CR85 0x85
287#define CR86 0x86
288#define CR87 0x87
289#define CR88 0x88
290#define CR89 0x89
291#define CR8A 0x8A
292#define CR8B 0x8B
293#define CR8C 0x8C
294#define CR8D 0x8D
295#define CR8E 0x8E
296#define CR8F 0x8F
297#define CR90 0x90
298#define CR91 0x91
299#define CR92 0x92
300#define CR93 0x93
301#define CR94 0x94
302#define CR95 0x95
303#define CR96 0x96
304#define CR97 0x97
305#define CR98 0x98
306#define CR99 0x99
307#define CR9A 0x9A
308#define CR9B 0x9B
309#define CR9C 0x9C
310#define CR9D 0x9D
311#define CR9E 0x9E
312#define CR9F 0x9F
313#define CRA0 0xA0
314#define CRA1 0xA1
315#define CRA2 0xA2
316#define CRA3 0xA3
317#define CRD2 0xD2
318#define CRD3 0xD3
319#define CRD4 0xD4
320
321/* LUT Table*/
322#define LUT_DATA 0x3C9 /* DACDATA */
323#define LUT_INDEX_READ 0x3C7 /* DACRX */
324#define LUT_INDEX_WRITE 0x3C8 /* DACWX */
325#define DACMASK 0x3C6
326
327/* Definition Device */
328#define DEVICE_CRT 0x01
329#define DEVICE_DVI 0x03
330#define DEVICE_LCD 0x04
331
332/* Device output interface */
333#define INTERFACE_NONE 0x00
334#define INTERFACE_ANALOG_RGB 0x01
335#define INTERFACE_DVP0 0x02
336#define INTERFACE_DVP1 0x03
337#define INTERFACE_DFP_HIGH 0x04
338#define INTERFACE_DFP_LOW 0x05
339#define INTERFACE_DFP 0x06
340#define INTERFACE_LVDS0 0x07
341#define INTERFACE_LVDS1 0x08
342#define INTERFACE_LVDS0LVDS1 0x09
343#define INTERFACE_TMDS 0x0A
344
345#define HW_LAYOUT_LCD_ONLY 0x01
346#define HW_LAYOUT_DVI_ONLY 0x02
347#define HW_LAYOUT_LCD_DVI 0x03
348#define HW_LAYOUT_LCD1_LCD2 0x04
349#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
350
351/* Definition Refresh Rate */
352#define REFRESH_50 50
353#define REFRESH_60 60
354#define REFRESH_75 75
355#define REFRESH_85 85
356#define REFRESH_100 100
357#define REFRESH_120 120
358
359/* Definition Sync Polarity*/
360#define NEGATIVE 1
361#define POSITIVE 0
362
363/*480x640@60 Sync Polarity (GTF)
364*/
365#define M480X640_R60_HSP NEGATIVE
366#define M480X640_R60_VSP POSITIVE
367
368/*640x480@60 Sync Polarity (VESA Mode)
369*/
370#define M640X480_R60_HSP NEGATIVE
371#define M640X480_R60_VSP NEGATIVE
372
373/*640x480@75 Sync Polarity (VESA Mode)
374*/
375#define M640X480_R75_HSP NEGATIVE
376#define M640X480_R75_VSP NEGATIVE
377
378/*640x480@85 Sync Polarity (VESA Mode)
379*/
380#define M640X480_R85_HSP NEGATIVE
381#define M640X480_R85_VSP NEGATIVE
382
383/*640x480@100 Sync Polarity (GTF Mode)
384*/
385#define M640X480_R100_HSP NEGATIVE
386#define M640X480_R100_VSP POSITIVE
387
388/*640x480@120 Sync Polarity (GTF Mode)
389*/
390#define M640X480_R120_HSP NEGATIVE
391#define M640X480_R120_VSP POSITIVE
392
393/*720x480@60 Sync Polarity (GTF Mode)
394*/
395#define M720X480_R60_HSP NEGATIVE
396#define M720X480_R60_VSP POSITIVE
397
398/*720x576@60 Sync Polarity (GTF Mode)
399*/
400#define M720X576_R60_HSP NEGATIVE
401#define M720X576_R60_VSP POSITIVE
402
403/*800x600@60 Sync Polarity (VESA Mode)
404*/
405#define M800X600_R60_HSP POSITIVE
406#define M800X600_R60_VSP POSITIVE
407
408/*800x600@75 Sync Polarity (VESA Mode)
409*/
410#define M800X600_R75_HSP POSITIVE
411#define M800X600_R75_VSP POSITIVE
412
413/*800x600@85 Sync Polarity (VESA Mode)
414*/
415#define M800X600_R85_HSP POSITIVE
416#define M800X600_R85_VSP POSITIVE
417
418/*800x600@100 Sync Polarity (GTF Mode)
419*/
420#define M800X600_R100_HSP NEGATIVE
421#define M800X600_R100_VSP POSITIVE
422
423/*800x600@120 Sync Polarity (GTF Mode)
424*/
425#define M800X600_R120_HSP NEGATIVE
426#define M800X600_R120_VSP POSITIVE
427
428/*800x480@60 Sync Polarity (CVT Mode)
429*/
430#define M800X480_R60_HSP NEGATIVE
431#define M800X480_R60_VSP POSITIVE
432
433/*848x480@60 Sync Polarity (CVT Mode)
434*/
435#define M848X480_R60_HSP NEGATIVE
436#define M848X480_R60_VSP POSITIVE
437
438/*852x480@60 Sync Polarity (GTF Mode)
439*/
440#define M852X480_R60_HSP NEGATIVE
441#define M852X480_R60_VSP POSITIVE
442
443/*1024x512@60 Sync Polarity (GTF Mode)
444*/
445#define M1024X512_R60_HSP NEGATIVE
446#define M1024X512_R60_VSP POSITIVE
447
448/*1024x600@60 Sync Polarity (GTF Mode)
449*/
450#define M1024X600_R60_HSP NEGATIVE
451#define M1024X600_R60_VSP POSITIVE
452
453/*1024x768@60 Sync Polarity (VESA Mode)
454*/
455#define M1024X768_R60_HSP NEGATIVE
456#define M1024X768_R60_VSP NEGATIVE
457
458/*1024x768@75 Sync Polarity (VESA Mode)
459*/
460#define M1024X768_R75_HSP POSITIVE
461#define M1024X768_R75_VSP POSITIVE
462
463/*1024x768@85 Sync Polarity (VESA Mode)
464*/
465#define M1024X768_R85_HSP POSITIVE
466#define M1024X768_R85_VSP POSITIVE
467
468/*1024x768@100 Sync Polarity (GTF Mode)
469*/
470#define M1024X768_R100_HSP NEGATIVE
471#define M1024X768_R100_VSP POSITIVE
472
473/*1152x864@75 Sync Polarity (VESA Mode)
474*/
475#define M1152X864_R75_HSP POSITIVE
476#define M1152X864_R75_VSP POSITIVE
477
478/*1280x720@60 Sync Polarity (GTF Mode)
479*/
480#define M1280X720_R60_HSP NEGATIVE
481#define M1280X720_R60_VSP POSITIVE
482
483/* 1280x768@50 Sync Polarity (GTF Mode) */
484#define M1280X768_R50_HSP NEGATIVE
485#define M1280X768_R50_VSP POSITIVE
486
487/*1280x768@60 Sync Polarity (GTF Mode)
488*/
489#define M1280X768_R60_HSP NEGATIVE
490#define M1280X768_R60_VSP POSITIVE
491
492/*1280x800@60 Sync Polarity (CVT Mode)
493*/
494#define M1280X800_R60_HSP NEGATIVE
495#define M1280X800_R60_VSP POSITIVE
496
497/*1280x960@60 Sync Polarity (VESA Mode)
498*/
499#define M1280X960_R60_HSP POSITIVE
500#define M1280X960_R60_VSP POSITIVE
501
502/*1280x1024@60 Sync Polarity (VESA Mode)
503*/
504#define M1280X1024_R60_HSP POSITIVE
505#define M1280X1024_R60_VSP POSITIVE
506
507/* 1360x768@60 Sync Polarity (CVT Mode) */
508#define M1360X768_R60_HSP POSITIVE
509#define M1360X768_R60_VSP POSITIVE
510
511/* 1360x768@60 Sync Polarity (CVT Reduce Blanking Mode) */
512#define M1360X768_RB_R60_HSP POSITIVE
513#define M1360X768_RB_R60_VSP NEGATIVE
514
515/* 1368x768@50 Sync Polarity (GTF Mode) */
516#define M1368X768_R50_HSP NEGATIVE
517#define M1368X768_R50_VSP POSITIVE
518
519/* 1368x768@60 Sync Polarity (VESA Mode) */
520#define M1368X768_R60_HSP NEGATIVE
521#define M1368X768_R60_VSP POSITIVE
522
523/*1280x1024@75 Sync Polarity (VESA Mode)
524*/
525#define M1280X1024_R75_HSP POSITIVE
526#define M1280X1024_R75_VSP POSITIVE
527
528/*1280x1024@85 Sync Polarity (VESA Mode)
529*/
530#define M1280X1024_R85_HSP POSITIVE
531#define M1280X1024_R85_VSP POSITIVE
532
533/*1440x1050@60 Sync Polarity (GTF Mode)
534*/
535#define M1440X1050_R60_HSP NEGATIVE
536#define M1440X1050_R60_VSP POSITIVE
537
538/*1600x1200@60 Sync Polarity (VESA Mode)
539*/
540#define M1600X1200_R60_HSP POSITIVE
541#define M1600X1200_R60_VSP POSITIVE
542
543/*1600x1200@75 Sync Polarity (VESA Mode)
544*/
545#define M1600X1200_R75_HSP POSITIVE
546#define M1600X1200_R75_VSP POSITIVE
547
548/* 1680x1050@60 Sync Polarity (CVT Mode) */
549#define M1680x1050_R60_HSP NEGATIVE
550#define M1680x1050_R60_VSP NEGATIVE
551
552/* 1680x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
553#define M1680x1050_RB_R60_HSP POSITIVE
554#define M1680x1050_RB_R60_VSP NEGATIVE
555
556/* 1680x1050@75 Sync Polarity (CVT Mode) */
557#define M1680x1050_R75_HSP NEGATIVE
558#define M1680x1050_R75_VSP POSITIVE
559
560/*1920x1080@60 Sync Polarity (CVT Mode)
561*/
562#define M1920X1080_R60_HSP NEGATIVE
563#define M1920X1080_R60_VSP POSITIVE
564
565/* 1920x1080@60 Sync Polarity (CVT Reduce Blanking Mode) */
566#define M1920X1080_RB_R60_HSP POSITIVE
567#define M1920X1080_RB_R60_VSP NEGATIVE
568
569/*1920x1440@60 Sync Polarity (VESA Mode)
570*/
571#define M1920X1440_R60_HSP NEGATIVE
572#define M1920X1440_R60_VSP POSITIVE
573
574/*1920x1440@75 Sync Polarity (VESA Mode)
575*/
576#define M1920X1440_R75_HSP NEGATIVE
577#define M1920X1440_R75_VSP POSITIVE
578
579#if 0
580/* 1400x1050@60 Sync Polarity (VESA Mode) */
581#define M1400X1050_R60_HSP NEGATIVE
582#define M1400X1050_R60_VSP NEGATIVE
583#endif
584
585/* 1400x1050@60 Sync Polarity (CVT Mode) */
586#define M1400X1050_R60_HSP NEGATIVE
587#define M1400X1050_R60_VSP POSITIVE
588
589/* 1400x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
590#define M1400X1050_RB_R60_HSP POSITIVE
591#define M1400X1050_RB_R60_VSP NEGATIVE
592
593/* 1400x1050@75 Sync Polarity (CVT Mode) */
594#define M1400X1050_R75_HSP NEGATIVE
595#define M1400X1050_R75_VSP POSITIVE
596
597/* 960x600@60 Sync Polarity (CVT Mode) */
598#define M960X600_R60_HSP NEGATIVE
599#define M960X600_R60_VSP POSITIVE
600
601/* 1000x600@60 Sync Polarity (GTF Mode) */
602#define M1000X600_R60_HSP NEGATIVE
603#define M1000X600_R60_VSP POSITIVE
604
605/* 1024x576@60 Sync Polarity (GTF Mode) */
606#define M1024X576_R60_HSP NEGATIVE
607#define M1024X576_R60_VSP POSITIVE
608
609/*1024x600@60 Sync Polarity (GTF Mode)*/
610#define M1024X600_R60_HSP NEGATIVE
611#define M1024X600_R60_VSP POSITIVE
612
613/* 1088x612@60 Sync Polarity (CVT Mode) */
614#define M1088X612_R60_HSP NEGATIVE
615#define M1088X612_R60_VSP POSITIVE
616
617/* 1152x720@60 Sync Polarity (CVT Mode) */
618#define M1152X720_R60_HSP NEGATIVE
619#define M1152X720_R60_VSP POSITIVE
620
621/* 1200x720@60 Sync Polarity (GTF Mode) */
622#define M1200X720_R60_HSP NEGATIVE
623#define M1200X720_R60_VSP POSITIVE
624
625/* 1280x600@60 Sync Polarity (GTF Mode) */
626#define M1280x600_R60_HSP NEGATIVE
627#define M1280x600_R60_VSP POSITIVE
628
629/* 1280x720@50 Sync Polarity (GTF Mode) */
630#define M1280X720_R50_HSP NEGATIVE
631#define M1280X720_R50_VSP POSITIVE
632
633/* 1280x720@60 Sync Polarity (CEA Mode) */
634#define M1280X720_CEA_R60_HSP POSITIVE
635#define M1280X720_CEA_R60_VSP POSITIVE
636
637/* 1440x900@60 Sync Polarity (CVT Mode) */
638#define M1440X900_R60_HSP NEGATIVE
639#define M1440X900_R60_VSP POSITIVE
640
641/* 1440x900@75 Sync Polarity (CVT Mode) */
642#define M1440X900_R75_HSP NEGATIVE
643#define M1440X900_R75_VSP POSITIVE
644
645/* 1440x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
646#define M1440X900_RB_R60_HSP POSITIVE
647#define M1440X900_RB_R60_VSP NEGATIVE
648
649/* 1600x900@60 Sync Polarity (CVT Mode) */
650#define M1600X900_R60_HSP NEGATIVE
651#define M1600X900_R60_VSP POSITIVE
652
653/* 1600x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
654#define M1600X900_RB_R60_HSP POSITIVE
655#define M1600X900_RB_R60_VSP NEGATIVE
656
657/* 1600x1024@60 Sync Polarity (GTF Mode) */
658#define M1600X1024_R60_HSP NEGATIVE
659#define M1600X1024_R60_VSP POSITIVE
660
661/* 1792x1344@60 Sync Polarity (DMT Mode) */
662#define M1792x1344_R60_HSP NEGATIVE
663#define M1792x1344_R60_VSP POSITIVE
664
665/* 1856x1392@60 Sync Polarity (DMT Mode) */
666#define M1856x1392_R60_HSP NEGATIVE
667#define M1856x1392_R60_VSP POSITIVE
668
669/* 1920x1200@60 Sync Polarity (CVT Mode) */
670#define M1920X1200_R60_HSP NEGATIVE
671#define M1920X1200_R60_VSP POSITIVE
672
673/* 1920x1200@60 Sync Polarity (CVT Reduce Blanking Mode) */
674#define M1920X1200_RB_R60_HSP POSITIVE
675#define M1920X1200_RB_R60_VSP NEGATIVE
676
677/* 1920x1080@60 Sync Polarity (CEA Mode) */
678#define M1920X1080_CEA_R60_HSP POSITIVE
679#define M1920X1080_CEA_R60_VSP POSITIVE
680
681/* 2048x1536@60 Sync Polarity (CVT Mode) */
682#define M2048x1536_R60_HSP NEGATIVE
683#define M2048x1536_R60_VSP POSITIVE
684
685/* define PLL index: */
686#define CLK_25_175M 25175000
687#define CLK_26_880M 26880000
688#define CLK_29_581M 29581000
689#define CLK_31_490M 31490000
690#define CLK_31_500M 31500000
691#define CLK_31_728M 31728000
692#define CLK_32_668M 32688000
693#define CLK_36_000M 36000000
694#define CLK_40_000M 40000000
695#define CLK_41_291M 41291000
696#define CLK_43_163M 43163000
697#define CLK_45_250M 45250000 /* 45.46MHz */
698#define CLK_46_000M 46000000
699#define CLK_46_996M 46996000
700#define CLK_48_000M 48000000
701#define CLK_48_875M 48875000
702#define CLK_49_500M 49500000
703#define CLK_52_406M 52406000
704#define CLK_52_977M 52977000
705#define CLK_56_250M 56250000
706#define CLK_60_466M 60466000
707#define CLK_61_500M 61500000
708#define CLK_65_000M 65000000
709#define CLK_65_178M 65178000
710#define CLK_66_750M 66750000 /* 67.116MHz */
711#define CLK_68_179M 68179000
712#define CLK_69_924M 69924000
713#define CLK_70_159M 70159000
714#define CLK_72_000M 72000000
715#define CLK_74_270M 74270000
716#define CLK_78_750M 78750000
717#define CLK_80_136M 80136000
718#define CLK_83_375M 83375000
719#define CLK_83_950M 83950000
720#define CLK_84_750M 84750000 /* 84.537Mhz */
721#define CLK_85_860M 85860000
722#define CLK_88_750M 88750000
723#define CLK_94_500M 94500000
724#define CLK_97_750M 97750000
725#define CLK_101_000M 101000000
726#define CLK_106_500M 106500000
727#define CLK_108_000M 108000000
728#define CLK_113_309M 113309000
729#define CLK_118_840M 118840000
730#define CLK_119_000M 119000000
731#define CLK_121_750M 121750000 /* 121.704MHz */
732#define CLK_125_104M 125104000
733#define CLK_133_308M 133308000
734#define CLK_135_000M 135000000
735#define CLK_136_700M 136700000
736#define CLK_138_400M 138400000
737#define CLK_146_760M 146760000
738#define CLK_148_500M 148500000
739
740#define CLK_153_920M 153920000
741#define CLK_156_000M 156000000
742#define CLK_157_500M 157500000
743#define CLK_162_000M 162000000
744#define CLK_187_000M 187000000
745#define CLK_193_295M 193295000
746#define CLK_202_500M 202500000
747#define CLK_204_000M 204000000
748#define CLK_218_500M 218500000
749#define CLK_234_000M 234000000
750#define CLK_267_250M 267250000
751#define CLK_297_500M 297500000
752#define CLK_74_481M 74481000
753#define CLK_172_798M 172798000
754#define CLK_122_614M 122614000
755
756/* CLE266 PLL value
757*/
758#define CLE266_PLL_25_175M 0x0000C763
759#define CLE266_PLL_26_880M 0x0000440F
760#define CLE266_PLL_29_581M 0x00008421
761#define CLE266_PLL_31_490M 0x00004721
762#define CLE266_PLL_31_500M 0x0000C3B5
763#define CLE266_PLL_31_728M 0x0000471F
764#define CLE266_PLL_32_668M 0x0000C449
765#define CLE266_PLL_36_000M 0x0000C5E5
766#define CLE266_PLL_40_000M 0x0000C459
767#define CLE266_PLL_41_291M 0x00004417
768#define CLE266_PLL_43_163M 0x0000C579
769#define CLE266_PLL_45_250M 0x0000C57F /* 45.46MHz */
770#define CLE266_PLL_46_000M 0x0000875A
771#define CLE266_PLL_46_996M 0x0000C4E9
772#define CLE266_PLL_48_000M 0x00001443
773#define CLE266_PLL_48_875M 0x00001D63
774#define CLE266_PLL_49_500M 0x00008653
775#define CLE266_PLL_52_406M 0x0000C475
776#define CLE266_PLL_52_977M 0x00004525
777#define CLE266_PLL_56_250M 0x000047B7
778#define CLE266_PLL_60_466M 0x0000494C
779#define CLE266_PLL_61_500M 0x00001456
780#define CLE266_PLL_65_000M 0x000086ED
781#define CLE266_PLL_65_178M 0x0000855B
782#define CLE266_PLL_66_750M 0x0000844B /* 67.116MHz */
783#define CLE266_PLL_68_179M 0x00000413
784#define CLE266_PLL_69_924M 0x00001153
785#define CLE266_PLL_70_159M 0x00001462
786#define CLE266_PLL_72_000M 0x00001879
787#define CLE266_PLL_74_270M 0x00004853
788#define CLE266_PLL_78_750M 0x00004321
789#define CLE266_PLL_80_136M 0x0000051C
790#define CLE266_PLL_83_375M 0x0000C25D
791#define CLE266_PLL_83_950M 0x00000729
792#define CLE266_PLL_84_750M 0x00008576 /* 84.537MHz */
793#define CLE266_PLL_85_860M 0x00004754
794#define CLE266_PLL_88_750M 0x0000051F
795#define CLE266_PLL_94_500M 0x00000521
796#define CLE266_PLL_97_750M 0x00004652
797#define CLE266_PLL_101_000M 0x0000497F
798#define CLE266_PLL_106_500M 0x00008477 /* 106.491463 MHz */
799#define CLE266_PLL_108_000M 0x00008479
800#define CLE266_PLL_113_309M 0x00000C5F
801#define CLE266_PLL_118_840M 0x00004553
802#define CLE266_PLL_119_000M 0x00000D6C
803#define CLE266_PLL_121_750M 0x00004555 /* 121.704MHz */
804#define CLE266_PLL_125_104M 0x000006B5
805#define CLE266_PLL_133_308M 0x0000465F
806#define CLE266_PLL_135_000M 0x0000455E
807#define CLE266_PLL_136_700M 0x00000C73
808#define CLE266_PLL_138_400M 0x00000957
809#define CLE266_PLL_146_760M 0x00004567
810#define CLE266_PLL_148_500M 0x00000853
811#define CLE266_PLL_153_920M 0x00000856
812#define CLE266_PLL_156_000M 0x0000456D
813#define CLE266_PLL_157_500M 0x000005B7
814#define CLE266_PLL_162_000M 0x00004571
815#define CLE266_PLL_187_000M 0x00000976
816#define CLE266_PLL_193_295M 0x0000086C
817#define CLE266_PLL_202_500M 0x00000763
818#define CLE266_PLL_204_000M 0x00000764
819#define CLE266_PLL_218_500M 0x0000065C
820#define CLE266_PLL_234_000M 0x00000662
821#define CLE266_PLL_267_250M 0x00000670
822#define CLE266_PLL_297_500M 0x000005E6
823#define CLE266_PLL_74_481M 0x0000051A
824#define CLE266_PLL_172_798M 0x00004579
825#define CLE266_PLL_122_614M 0x0000073C
826
827/* K800 PLL value
828*/
829#define K800_PLL_25_175M 0x00539001
830#define K800_PLL_26_880M 0x001C8C80
831#define K800_PLL_29_581M 0x00409080
832#define K800_PLL_31_490M 0x006F9001
833#define K800_PLL_31_500M 0x008B9002
834#define K800_PLL_31_728M 0x00AF9003
835#define K800_PLL_32_668M 0x00909002
836#define K800_PLL_36_000M 0x009F9002
837#define K800_PLL_40_000M 0x00578C02
838#define K800_PLL_41_291M 0x00438C01
839#define K800_PLL_43_163M 0x00778C03
840#define K800_PLL_45_250M 0x007D8C83 /* 45.46MHz */
841#define K800_PLL_46_000M 0x00658C02
842#define K800_PLL_46_996M 0x00818C83
843#define K800_PLL_48_000M 0x00848C83
844#define K800_PLL_48_875M 0x00508C81
845#define K800_PLL_49_500M 0x00518C01
846#define K800_PLL_52_406M 0x00738C02
847#define K800_PLL_52_977M 0x00928C83
848#define K800_PLL_56_250M 0x007C8C02
849#define K800_PLL_60_466M 0x00A78C83
850#define K800_PLL_61_500M 0x00AA8C83
851#define K800_PLL_65_000M 0x006B8C01
852#define K800_PLL_65_178M 0x00B48C83
853#define K800_PLL_66_750M 0x00948C82 /* 67.116MHz */
854#define K800_PLL_68_179M 0x00708C01
855#define K800_PLL_69_924M 0x00C18C83
856#define K800_PLL_70_159M 0x00C28C83
857#define K800_PLL_72_000M 0x009F8C82
858#define K800_PLL_74_270M 0x00ce0c03
859#define K800_PLL_78_750M 0x00408801
860#define K800_PLL_80_136M 0x00428801
861#define K800_PLL_83_375M 0x005B0882
862#define K800_PLL_83_950M 0x00738803
863#define K800_PLL_84_750M 0x00748883 /* 84.477MHz */
864#define K800_PLL_85_860M 0x00768883
865#define K800_PLL_88_750M 0x007A8883
866#define K800_PLL_94_500M 0x00828803
867#define K800_PLL_97_750M 0x00878883
868#define K800_PLL_101_000M 0x008B8883
869#define K800_PLL_106_500M 0x00758882 /* 106.491463 MHz */
870#define K800_PLL_108_000M 0x00778882
871#define K800_PLL_113_309M 0x005D8881
872#define K800_PLL_118_840M 0x00A48883
873#define K800_PLL_119_000M 0x00838882
874#define K800_PLL_121_750M 0x00A88883 /* 121.704MHz */
875#define K800_PLL_125_104M 0x00688801
876#define K800_PLL_133_308M 0x005D8801
877#define K800_PLL_135_000M 0x001A4081
878#define K800_PLL_136_700M 0x00BD8883
879#define K800_PLL_138_400M 0x00728881
880#define K800_PLL_146_760M 0x00CC8883
881#define K800_PLL_148_500M 0x00ce0803
882#define K800_PLL_153_920M 0x00548482
883#define K800_PLL_156_000M 0x006B8483
884#define K800_PLL_157_500M 0x00142080
885#define K800_PLL_162_000M 0x006F8483
886#define K800_PLL_187_000M 0x00818483
887#define K800_PLL_193_295M 0x004F8481
888#define K800_PLL_202_500M 0x00538481
889#define K800_PLL_204_000M 0x008D8483
890#define K800_PLL_218_500M 0x00978483
891#define K800_PLL_234_000M 0x00608401
892#define K800_PLL_267_250M 0x006E8481
893#define K800_PLL_297_500M 0x00A48402
894#define K800_PLL_74_481M 0x007B8C81
895#define K800_PLL_172_798M 0x00778483
896#define K800_PLL_122_614M 0x00878882
897
898/* PLL for VT3324 */
899#define CX700_25_175M 0x008B1003
900#define CX700_26_719M 0x00931003
901#define CX700_26_880M 0x00941003
902#define CX700_29_581M 0x00A49003
903#define CX700_31_490M 0x00AE1003
904#define CX700_31_500M 0x00AE1003
905#define CX700_31_728M 0x00AF1003
906#define CX700_32_668M 0x00B51003
907#define CX700_36_000M 0x00C81003
908#define CX700_40_000M 0x006E0C03
909#define CX700_41_291M 0x00710C03
910#define CX700_43_163M 0x00770C03
911#define CX700_45_250M 0x007D0C03 /* 45.46MHz */
912#define CX700_46_000M 0x007F0C03
913#define CX700_46_996M 0x00818C83
914#define CX700_48_000M 0x00840C03
915#define CX700_48_875M 0x00508C81
916#define CX700_49_500M 0x00880C03
917#define CX700_52_406M 0x00730C02
918#define CX700_52_977M 0x00920C03
919#define CX700_56_250M 0x009B0C03
920#define CX700_60_466M 0x00460C00
921#define CX700_61_500M 0x00AA0C03
922#define CX700_65_000M 0x006B0C01
923#define CX700_65_178M 0x006B0C01
924#define CX700_66_750M 0x00940C02 /*67.116MHz */
925#define CX700_68_179M 0x00BC0C03
926#define CX700_69_924M 0x00C10C03
927#define CX700_70_159M 0x00C20C03
928#define CX700_72_000M 0x009F0C02
929#define CX700_74_270M 0x00CE0C03
930#define CX700_74_481M 0x00CE0C03
931#define CX700_78_750M 0x006C0803
932#define CX700_80_136M 0x006E0803
933#define CX700_83_375M 0x005B0882
934#define CX700_83_950M 0x00730803
935#define CX700_84_750M 0x00740803 /* 84.537Mhz */
936#define CX700_85_860M 0x00760803
937#define CX700_88_750M 0x00AC8885
938#define CX700_94_500M 0x00820803
939#define CX700_97_750M 0x00870803
940#define CX700_101_000M 0x008B0803
941#define CX700_106_500M 0x00750802
942#define CX700_108_000M 0x00950803
943#define CX700_113_309M 0x005D0801
944#define CX700_118_840M 0x00A40803
945#define CX700_119_000M 0x00830802
946#define CX700_121_750M 0x00420800 /* 121.704MHz */
947#define CX700_125_104M 0x00AD0803
948#define CX700_133_308M 0x00930802
949#define CX700_135_000M 0x00950802
950#define CX700_136_700M 0x00BD0803
951#define CX700_138_400M 0x00720801
952#define CX700_146_760M 0x00CC0803
953#define CX700_148_500M 0x00a40802
954#define CX700_153_920M 0x00540402
955#define CX700_156_000M 0x006B0403
956#define CX700_157_500M 0x006C0403
957#define CX700_162_000M 0x006F0403
958#define CX700_172_798M 0x00770403
959#define CX700_187_000M 0x00810403
960#define CX700_193_295M 0x00850403
961#define CX700_202_500M 0x008C0403
962#define CX700_204_000M 0x008D0403
963#define CX700_218_500M 0x00970403
964#define CX700_234_000M 0x00600401
965#define CX700_267_250M 0x00B90403
966#define CX700_297_500M 0x00CE0403
967#define CX700_122_614M 0x00870802
968
969/* Definition CRTC Timing Index */
970#define H_TOTAL_INDEX 0
971#define H_ADDR_INDEX 1
972#define H_BLANK_START_INDEX 2
973#define H_BLANK_END_INDEX 3
974#define H_SYNC_START_INDEX 4
975#define H_SYNC_END_INDEX 5
976#define V_TOTAL_INDEX 6
977#define V_ADDR_INDEX 7
978#define V_BLANK_START_INDEX 8
979#define V_BLANK_END_INDEX 9
980#define V_SYNC_START_INDEX 10
981#define V_SYNC_END_INDEX 11
982#define H_TOTAL_SHADOW_INDEX 12
983#define H_BLANK_END_SHADOW_INDEX 13
984#define V_TOTAL_SHADOW_INDEX 14
985#define V_ADDR_SHADOW_INDEX 15
986#define V_BLANK_SATRT_SHADOW_INDEX 16
987#define V_BLANK_END_SHADOW_INDEX 17
988#define V_SYNC_SATRT_SHADOW_INDEX 18
989#define V_SYNC_END_SHADOW_INDEX 19
990
991/* Definition Video Mode Pixel Clock (picoseconds)
992*/
993#define RES_480X640_60HZ_PIXCLOCK 39722
994#define RES_640X480_60HZ_PIXCLOCK 39722
995#define RES_640X480_75HZ_PIXCLOCK 31747
996#define RES_640X480_85HZ_PIXCLOCK 27777
997#define RES_640X480_100HZ_PIXCLOCK 23168
998#define RES_640X480_120HZ_PIXCLOCK 19081
999#define RES_720X480_60HZ_PIXCLOCK 37020
1000#define RES_720X576_60HZ_PIXCLOCK 30611
1001#define RES_800X600_60HZ_PIXCLOCK 25000
1002#define RES_800X600_75HZ_PIXCLOCK 20203
1003#define RES_800X600_85HZ_PIXCLOCK 17777
1004#define RES_800X600_100HZ_PIXCLOCK 14667
1005#define RES_800X600_120HZ_PIXCLOCK 11912
1006#define RES_800X480_60HZ_PIXCLOCK 33805
1007#define RES_848X480_60HZ_PIXCLOCK 31756
1008#define RES_856X480_60HZ_PIXCLOCK 31518
1009#define RES_1024X512_60HZ_PIXCLOCK 24218
1010#define RES_1024X600_60HZ_PIXCLOCK 20460
1011#define RES_1024X768_60HZ_PIXCLOCK 15385
1012#define RES_1024X768_75HZ_PIXCLOCK 12699
1013#define RES_1024X768_85HZ_PIXCLOCK 10582
1014#define RES_1024X768_100HZ_PIXCLOCK 8825
1015#define RES_1152X864_75HZ_PIXCLOCK 9259
1016#define RES_1280X768_60HZ_PIXCLOCK 12480
1017#define RES_1280X800_60HZ_PIXCLOCK 11994
1018#define RES_1280X960_60HZ_PIXCLOCK 9259
1019#define RES_1280X1024_60HZ_PIXCLOCK 9260
1020#define RES_1280X1024_75HZ_PIXCLOCK 7408
1021#define RES_1280X768_85HZ_PIXCLOCK 6349
1022#define RES_1440X1050_60HZ_PIXCLOCK 7993
1023#define RES_1600X1200_60HZ_PIXCLOCK 6172
1024#define RES_1600X1200_75HZ_PIXCLOCK 4938
1025#define RES_1280X720_60HZ_PIXCLOCK 13426
1026#define RES_1920X1080_60HZ_PIXCLOCK 5787
1027#define RES_1400X1050_60HZ_PIXCLOCK 8214
1028#define RES_1400X1050_75HZ_PIXCLOCK 6410
1029#define RES_1368X768_60HZ_PIXCLOCK 11647
1030#define RES_960X600_60HZ_PIXCLOCK 22099
1031#define RES_1000X600_60HZ_PIXCLOCK 20834
1032#define RES_1024X576_60HZ_PIXCLOCK 21278
1033#define RES_1088X612_60HZ_PIXCLOCK 18877
1034#define RES_1152X720_60HZ_PIXCLOCK 14981
1035#define RES_1200X720_60HZ_PIXCLOCK 14253
1036#define RES_1280X600_60HZ_PIXCLOCK 16260
1037#define RES_1280X720_50HZ_PIXCLOCK 16538
1038#define RES_1280X768_50HZ_PIXCLOCK 15342
1039#define RES_1366X768_50HZ_PIXCLOCK 14301
1040#define RES_1366X768_60HZ_PIXCLOCK 11646
1041#define RES_1360X768_60HZ_PIXCLOCK 11799
1042#define RES_1440X900_60HZ_PIXCLOCK 9390
1043#define RES_1440X900_75HZ_PIXCLOCK 7315
1044#define RES_1600X900_60HZ_PIXCLOCK 8415
1045#define RES_1600X1024_60HZ_PIXCLOCK 7315
1046#define RES_1680X1050_60HZ_PIXCLOCK 6814
1047#define RES_1680X1050_75HZ_PIXCLOCK 5348
1048#define RES_1792X1344_60HZ_PIXCLOCK 4902
1049#define RES_1856X1392_60HZ_PIXCLOCK 4577
1050#define RES_1920X1200_60HZ_PIXCLOCK 5173
1051#define RES_1920X1440_60HZ_PIXCLOCK 4274
1052#define RES_1920X1440_75HZ_PIXCLOCK 3367
1053#define RES_2048X1536_60HZ_PIXCLOCK 3742
1054
1055#define RES_1360X768_RB_60HZ_PIXCLOCK 13889
1056#define RES_1400X1050_RB_60HZ_PIXCLOCK 9901
1057#define RES_1440X900_RB_60HZ_PIXCLOCK 11268
1058#define RES_1600X900_RB_60HZ_PIXCLOCK 10230
1059#define RES_1680X1050_RB_60HZ_PIXCLOCK 8403
1060#define RES_1920X1080_RB_60HZ_PIXCLOCK 7225
1061#define RES_1920X1200_RB_60HZ_PIXCLOCK 6497
1062
1063/* LCD display method
1064*/
1065#define LCD_EXPANDSION 0x00
1066#define LCD_CENTERING 0x01
1067
1068/* LCD mode
1069*/
1070#define LCD_OPENLDI 0x00
1071#define LCD_SPWG 0x01
1072
1073/* Define display timing
1074*/
1075struct display_timing {
1076 u16 hor_total;
1077 u16 hor_addr;
1078 u16 hor_blank_start;
1079 u16 hor_blank_end;
1080 u16 hor_sync_start;
1081 u16 hor_sync_end;
1082 u16 ver_total;
1083 u16 ver_addr;
1084 u16 ver_blank_start;
1085 u16 ver_blank_end;
1086 u16 ver_sync_start;
1087 u16 ver_sync_end;
1088};
1089
1090struct crt_mode_table {
1091 int refresh_rate;
1092 unsigned long clk;
1093 int h_sync_polarity;
1094 int v_sync_polarity;
1095 struct display_timing crtc;
1096};
1097
1098struct io_reg {
1099 int port;
1100 u8 index;
1101 u8 mask;
1102 u8 value;
1103};
1104
1105#endif /* __SHARE_H__ */
diff --git a/drivers/video/via/tbl1636.c b/drivers/video/via/tbl1636.c
new file mode 100644
index 000000000000..2d8453429d4a
--- /dev/null
+++ b/drivers/video/via/tbl1636.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23struct IODATA COMMON_INIT_TBL_VT1636[] = {
24/* Index, Mask, Value */
25 /* Set panel power sequence timing */
26 {0x10, 0xC0, 0x00},
27 /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
28 {0x0B, 0xFF, 0x40},
29 /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
30 {0x0C, 0xFF, 0x31},
31 /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
32 {0x0D, 0xFF, 0x31},
33 /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
34 {0x0E, 0xFF, 0x68},
35 /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
36 {0x0F, 0xFF, 0x68},
37 /* LVDS output power up */
38 {0x09, 0xA0, 0xA0},
39 /* turn on back light */
40 {0x10, 0x33, 0x13}
41};
42
43struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[] = {
44/* Index, Mask, Value */
45 {0x08, 0xF0, 0xE0} /* Input Data Mode Select */
46};
47
48struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[] = {
49/* Index, Mask, Value */
50 {0x08, 0xF0, 0x00} /* Input Data Mode Select */
51};
52
53struct IODATA DITHERING_ENABLE_TBL_VT1636[] = {
54/* Index, Mask, Value */
55 {0x0A, 0x70, 0x50}
56};
57
58struct IODATA DITHERING_DISABLE_TBL_VT1636[] = {
59/* Index, Mask, Value */
60 {0x0A, 0x70, 0x00}
61};
62
63struct IODATA VDD_ON_TBL_VT1636[] = {
64/* Index, Mask, Value */
65 {0x10, 0x20, 0x20}
66};
67
68struct IODATA VDD_OFF_TBL_VT1636[] = {
69/* Index, Mask, Value */
70 {0x10, 0x20, 0x00}
71};
diff --git a/drivers/video/via/tbl1636.h b/drivers/video/via/tbl1636.h
new file mode 100644
index 000000000000..d906055f1511
--- /dev/null
+++ b/drivers/video/via/tbl1636.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef _TBL1636_H_
23#define _TBL1636_H_
24#include "hw.h"
25
26extern struct IODATA COMMON_INIT_TBL_VT1636[8];
27extern struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[1];
28extern struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[1];
29extern struct IODATA DITHERING_ENABLE_TBL_VT1636[1];
30extern struct IODATA DITHERING_DISABLE_TBL_VT1636[1];
31extern struct IODATA VDD_ON_TBL_VT1636[1];
32extern struct IODATA VDD_OFF_TBL_VT1636[1];
33
34#endif /* _VIA_TBL1636_H_ */
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/via/tblDPASetting.c
new file mode 100644
index 000000000000..0c4c8cc712f4
--- /dev/null
+++ b/drivers/video/via/tblDPASetting.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23/* For VT3324: */
24struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[] = {
25 /* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */
26 {LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */
27 {LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */
28 {LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */
29 {LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */
30 {LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */
31 {LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */
32 {LCD_PANEL_ID6_1600X1200, 0x0B, 0x03} /* For 1600x1200 */
33};
34
35struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
36/* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
37 DVP1Driving, DFPHigh, DFPLow */
38/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
39 SR65, CR97, CR99 */
40 /* LCK/VCK < 30000000 will use this value */
41 {DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
42 0x00},
43 /* 30000000 < LCK/VCK < 50000000 will use this value */
44 {DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
45 0x00},
46 /* 50000000 < LCK/VCK < 70000000 will use this value */
47 {DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
48 0x00},
49 /* 70000000 < LCK/VCK < 100000000 will use this value */
50 {DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
51 0x00},
52 /* 100000000 < LCK/VCK < 15000000 will use this value */
53 {DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
54 0x00},
55 /* 15000000 < LCK/VCK will use this value */
56 {DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
57 0x00},
58};
59
60/* For VT3327: */
61struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[] = {
62 /* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */
63 {LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */
64 {LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */
65 {LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */
66 {LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */
67 {LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */
68 {LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */
69 {LCD_PANEL_ID6_1600X1200, 0x00, 0x00} /* For 1600x1200 */
70};
71
72struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
73/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
74 DVP1Driving, DFPHigh, DFPLow */
75/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
76 SR65, CR97, CR99 */
77/* LCK/VCK < 30000000 will use this value */
78{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
79/* 30000000 < LCK/VCK < 50000000 will use this value */
80{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
81/* 50000000 < LCK/VCK < 70000000 will use this value */
82{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
83/* 70000000 < LCK/VCK < 100000000 will use this value */
84{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
85/* 100000000 < LCK/VCK < 15000000 will use this value */
86{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
87/* 15000000 < LCK/VCK will use this value */
88{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
89};
90
91/* For VT3364: */
92struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
93/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
94 DVP1Driving, DFPHigh, DFPLow */
95/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
96 SR65, CR97, CR99 */
97/* LCK/VCK < 30000000 will use this value */
98{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
99/* 30000000 < LCK/VCK < 50000000 will use this value */
100{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
101/* 50000000 < LCK/VCK < 70000000 will use this value */
102{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
103/* 70000000 < LCK/VCK < 100000000 will use this value */
104{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
105/* 100000000 < LCK/VCK < 15000000 will use this value */
106{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
107/* 15000000 < LCK/VCK will use this value */
108{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
109};
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h
new file mode 100644
index 000000000000..b065a83481d3
--- /dev/null
+++ b/drivers/video/via/tblDPASetting.h
@@ -0,0 +1,47 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef _TBLDPASETTING_H_
23#define _TBLDPASETTING_H_
24#include "global.h"
25
26#define DPA_CLK_30M 30000000
27#define DPA_CLK_50M 50000000
28#define DPA_CLK_70M 70000000
29#define DPA_CLK_100M 100000000
30#define DPA_CLK_150M 150000000
31
32enum DPA_RANGE {
33 DPA_CLK_RANGE_30M,
34 DPA_CLK_RANGE_30_50M,
35 DPA_CLK_RANGE_50_70M,
36 DPA_CLK_RANGE_70_100M,
37 DPA_CLK_RANGE_100_150M,
38 DPA_CLK_RANGE_150M
39};
40
41extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7];
42extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
43extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[7];
44extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
45extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
46
47#endif
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
new file mode 100644
index 000000000000..0f3ed4eb236d
--- /dev/null
+++ b/drivers/video/via/via_i2c.c
@@ -0,0 +1,177 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24static void via_i2c_setscl(void *data, int state)
25{
26 u8 val;
27 struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
28
29 val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
30 if (state)
31 val |= 0x20;
32 else
33 val &= ~0x20;
34 switch (via_i2c_chan->i2c_port) {
35 case I2CPORTINDEX:
36 val |= 0x01;
37 break;
38 case GPIOPORTINDEX:
39 val |= 0x80;
40 break;
41 default:
42 DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
43 }
44 viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
45}
46
47static int via_i2c_getscl(void *data)
48{
49 struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
50
51 if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08)
52 return 1;
53 return 0;
54}
55
56static int via_i2c_getsda(void *data)
57{
58 struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
59
60 if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04)
61 return 1;
62 return 0;
63}
64
65static void via_i2c_setsda(void *data, int state)
66{
67 u8 val;
68 struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
69
70 val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
71 if (state)
72 val |= 0x10;
73 else
74 val &= ~0x10;
75 switch (via_i2c_chan->i2c_port) {
76 case I2CPORTINDEX:
77 val |= 0x01;
78 break;
79 case GPIOPORTINDEX:
80 val |= 0x40;
81 break;
82 default:
83 DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
84 }
85 viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
86}
87
88int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
89{
90 u8 mm1[] = {0x00};
91 struct i2c_msg msgs[2];
92
93 *pdata = 0;
94 msgs[0].flags = 0;
95 msgs[1].flags = I2C_M_RD;
96 msgs[0].addr = msgs[1].addr = slave_addr / 2;
97 mm1[0] = index;
98 msgs[0].len = 1; msgs[1].len = 1;
99 msgs[0].buf = mm1; msgs[1].buf = pdata;
100 i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
101
102 return 0;
103}
104
105int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data)
106{
107 u8 msg[2] = { index, data };
108 struct i2c_msg msgs;
109
110 msgs.flags = 0;
111 msgs.addr = slave_addr / 2;
112 msgs.len = 2;
113 msgs.buf = msg;
114 return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1);
115}
116
117int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
118{
119 u8 mm1[] = {0x00};
120 struct i2c_msg msgs[2];
121
122 msgs[0].flags = 0;
123 msgs[1].flags = I2C_M_RD;
124 msgs[0].addr = msgs[1].addr = slave_addr / 2;
125 mm1[0] = index;
126 msgs[0].len = 1; msgs[1].len = buff_len;
127 msgs[0].buf = mm1; msgs[1].buf = buff;
128 i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
129 return 0;
130}
131
132int viafb_create_i2c_bus(void *viapar)
133{
134 int ret;
135 struct viafb_par *par = (struct viafb_par *)viapar;
136
137 strcpy(par->i2c_stuff.adapter.name, "via_i2c");
138 par->i2c_stuff.i2c_port = 0x0;
139 par->i2c_stuff.adapter.owner = THIS_MODULE;
140 par->i2c_stuff.adapter.id = 0x01FFFF;
141 par->i2c_stuff.adapter.class = 0;
142 par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo;
143 par->i2c_stuff.adapter.dev.parent = NULL;
144 par->i2c_stuff.algo.setsda = via_i2c_setsda;
145 par->i2c_stuff.algo.setscl = via_i2c_setscl;
146 par->i2c_stuff.algo.getsda = via_i2c_getsda;
147 par->i2c_stuff.algo.getscl = via_i2c_getscl;
148 par->i2c_stuff.algo.udelay = 40;
149 par->i2c_stuff.algo.timeout = 20;
150 par->i2c_stuff.algo.data = &par->i2c_stuff;
151
152 i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff);
153
154 /* Raise SCL and SDA */
155 par->i2c_stuff.i2c_port = I2CPORTINDEX;
156 via_i2c_setsda(&par->i2c_stuff, 1);
157 via_i2c_setscl(&par->i2c_stuff, 1);
158
159 par->i2c_stuff.i2c_port = GPIOPORTINDEX;
160 via_i2c_setsda(&par->i2c_stuff, 1);
161 via_i2c_setscl(&par->i2c_stuff, 1);
162 udelay(20);
163
164 ret = i2c_bit_add_bus(&par->i2c_stuff.adapter);
165 if (ret == 0)
166 DEBUG_MSG("I2C bus %s registered.\n",
167 par->i2c_stuff.adapter.name);
168 else
169 DEBUG_MSG("Failed to register I2C bus %s.\n",
170 par->i2c_stuff.adapter.name);
171 return ret;
172}
173
174void viafb_delete_i2c_buss(void *par)
175{
176 i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter);
177}
diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h
new file mode 100644
index 000000000000..3a13242a3152
--- /dev/null
+++ b/drivers/video/via/via_i2c.h
@@ -0,0 +1,46 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __VIA_I2C_H__
22#define __VIA_I2C_H__
23
24#include <linux/i2c.h>
25#include <linux/i2c-algo-bit.h>
26
27struct via_i2c_stuff {
28 u16 i2c_port; /* GPIO or I2C port */
29 struct i2c_adapter adapter;
30 struct i2c_algo_bit_data algo;
31};
32
33#define I2CPORT 0x3c4
34#define I2CPORTINDEX 0x31
35#define GPIOPORT 0x3C4
36#define GPIOPORTINDEX 0x2C
37#define I2C_BUS 1
38#define GPIO_BUS 2
39#define DELAYPORT 0x3C3
40
41int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata);
42int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data);
43int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len);
44int viafb_create_i2c_bus(void *par);
45void viafb_delete_i2c_buss(void *par);
46#endif /* __VIA_I2C_H__ */
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
new file mode 100644
index 000000000000..d53c3d54ed8e
--- /dev/null
+++ b/drivers/video/via/via_utility.c
@@ -0,0 +1,253 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24void viafb_get_device_support_state(u32 *support_state)
25{
26 *support_state = CRT_Device;
27
28 if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
29 *support_state |= DVI_Device;
30
31 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
32 *support_state |= LCD_Device;
33}
34
35void viafb_get_device_connect_state(u32 *connect_state)
36{
37 bool mobile = false;
38
39 *connect_state = CRT_Device;
40
41 if (viafb_dvi_sense())
42 *connect_state |= DVI_Device;
43
44 viafb_lcd_get_mobile_state(&mobile);
45 if (mobile)
46 *connect_state |= LCD_Device;
47}
48
49bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
50{
51 unsigned int support_state = 0;
52
53 switch (viafb_lcd_panel_id) {
54 case LCD_PANEL_ID0_640X480:
55 if ((xres < 640) && (yres < 480))
56 support_state = true;
57 break;
58
59 case LCD_PANEL_ID1_800X600:
60 if ((xres < 800) && (yres < 600))
61 support_state = true;
62 break;
63
64 case LCD_PANEL_ID2_1024X768:
65 if ((xres < 1024) && (yres < 768))
66 support_state = true;
67 break;
68
69 case LCD_PANEL_ID3_1280X768:
70 if ((xres < 1280) && (yres < 768))
71 support_state = true;
72 break;
73
74 case LCD_PANEL_ID4_1280X1024:
75 if ((xres < 1280) && (yres < 1024))
76 support_state = true;
77 break;
78
79 case LCD_PANEL_ID5_1400X1050:
80 if ((xres < 1400) && (yres < 1050))
81 support_state = true;
82 break;
83
84 case LCD_PANEL_ID6_1600X1200:
85 if ((xres < 1600) && (yres < 1200))
86 support_state = true;
87 break;
88
89 case LCD_PANEL_ID7_1366X768:
90 if ((xres < 1366) && (yres < 768))
91 support_state = true;
92 break;
93
94 case LCD_PANEL_ID8_1024X600:
95 if ((xres < 1024) && (yres < 600))
96 support_state = true;
97 break;
98
99 case LCD_PANEL_ID9_1280X800:
100 if ((xres < 1280) && (yres < 800))
101 support_state = true;
102 break;
103
104 case LCD_PANEL_IDA_800X480:
105 if ((xres < 800) && (yres < 480))
106 support_state = true;
107 break;
108
109 case LCD_PANEL_IDB_1360X768:
110 if ((xres < 1360) && (yres < 768))
111 support_state = true;
112 break;
113
114 case LCD_PANEL_IDC_480X640:
115 if ((xres < 480) && (yres < 640))
116 support_state = true;
117 break;
118
119 default:
120 support_state = false;
121 break;
122 }
123
124 return support_state;
125}
126
127/*====================================================================*/
128/* Gamma Function Implementation*/
129/*====================================================================*/
130
131void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
132{
133 int i, sr1a;
134 int active_device_amount = 0;
135 int device_status = viafb_DeviceStatus;
136
137 for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
138 if (device_status & 1)
139 active_device_amount++;
140 device_status >>= 1;
141 }
142
143 /* 8 bpp mode can't adjust gamma */
144 if (bpp == 8)
145 return ;
146
147 /* Enable Gamma */
148 switch (viaparinfo->chip_info->gfx_chip_name) {
149 case UNICHROME_CLE266:
150 case UNICHROME_K400:
151 viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
152 break;
153
154 case UNICHROME_K800:
155 case UNICHROME_PM800:
156 case UNICHROME_CN700:
157 case UNICHROME_CX700:
158 case UNICHROME_K8M890:
159 case UNICHROME_P4M890:
160 case UNICHROME_P4M900:
161 viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
162 break;
163 }
164 sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
165 viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
166
167 /* Fill IGA1 Gamma Table */
168 outb(0, LUT_INDEX_WRITE);
169 for (i = 0; i < 256; i++) {
170 outb(gamma_table[i] >> 16, LUT_DATA);
171 outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
172 outb(gamma_table[i] & 0xFF, LUT_DATA);
173 }
174
175 /* If adjust Gamma value in SAMM, fill IGA1,
176 IGA2 Gamma table simultanous. */
177 /* Switch to IGA2 Gamma Table */
178 if ((active_device_amount > 1) &&
179 !((viaparinfo->chip_info->gfx_chip_name ==
180 UNICHROME_CLE266) &&
181 (viaparinfo->chip_info->gfx_chip_revision < 15))) {
182 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
183 viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
184
185 /* Fill IGA2 Gamma Table */
186 outb(0, LUT_INDEX_WRITE);
187 for (i = 0; i < 256; i++) {
188 outb(gamma_table[i] >> 16, LUT_DATA);
189 outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
190 outb(gamma_table[i] & 0xFF, LUT_DATA);
191 }
192 }
193 viafb_write_reg(SR1A, VIASR, sr1a);
194}
195
196void viafb_get_gamma_table(unsigned int *gamma_table)
197{
198 unsigned char color_r, color_g, color_b;
199 unsigned char sr1a = 0;
200 int i;
201
202 /* Enable Gamma */
203 switch (viaparinfo->chip_info->gfx_chip_name) {
204 case UNICHROME_CLE266:
205 case UNICHROME_K400:
206 viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
207 break;
208
209 case UNICHROME_K800:
210 case UNICHROME_PM800:
211 case UNICHROME_CN700:
212 case UNICHROME_CX700:
213 case UNICHROME_K8M890:
214 case UNICHROME_P4M890:
215 case UNICHROME_P4M900:
216 viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
217 break;
218 }
219 sr1a = viafb_read_reg(VIASR, SR1A);
220 viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
221
222 /* Reading gamma table to get color value */
223 outb(0, LUT_INDEX_READ);
224 for (i = 0; i < 256; i++) {
225 color_r = inb(LUT_DATA);
226 color_g = inb(LUT_DATA);
227 color_b = inb(LUT_DATA);
228 gamma_table[i] =
229 ((((u32) color_r) << 16) |
230 (((u16) color_g) << 8)) | color_b;
231 }
232 viafb_write_reg(SR1A, VIASR, sr1a);
233}
234
235void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
236{
237 if (bpp == 8)
238 *support_state = None_Device;
239 else
240 *support_state = CRT_Device | DVI_Device | LCD_Device;
241}
242
243int viafb_input_parameter_converter(int parameter_value)
244{
245 int result;
246
247 if (parameter_value >= 1 && parameter_value <= 9)
248 result = 1 << (parameter_value - 1);
249 else
250 result = 1;
251
252 return result;
253}
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
new file mode 100644
index 000000000000..2fd455202ebd
--- /dev/null
+++ b/drivers/video/via/via_utility.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __VIAUTILITY_H__
22#define __VIAUTILITY_H__
23
24/* These functions are used to get infomation about device's state */
25void viafb_get_device_support_state(u32 *support_state);
26void viafb_get_device_connect_state(u32 *connect_state);
27bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
28
29/* These function are used to access gamma table */
30void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
31void viafb_get_gamma_table(unsigned int *gamma_table);
32void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
33int viafb_input_parameter_converter(int parameter_value);
34
35#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
new file mode 100644
index 000000000000..0132eae06f55
--- /dev/null
+++ b/drivers/video/via/viafbdev.c
@@ -0,0 +1,2571 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/module.h>
23#define _MASTER_FILE
24
25#include "global.h"
26
27static int MAX_CURS = 32;
28static struct fb_var_screeninfo default_var;
29static char *viafb_name = "Via";
30static u32 pseudo_pal[17];
31
32/* video mode */
33static char *viafb_mode = "640x480";
34static char *viafb_mode1 = "640x480";
35static int viafb_resMode = VIA_RES_640X480;
36
37/* Added for specifying active devices.*/
38char *viafb_active_dev = "";
39
40/* Added for specifying video on devices.*/
41char *viafb_video_dev = "";
42
43/*Added for specify lcd output port*/
44char *viafb_lcd_port = "";
45char *viafb_dvi_port = "";
46
47static void viafb_set_device(struct device_t active_dev);
48static int apply_device_setting(struct viafb_ioctl_setting setting_info,
49 struct fb_info *info);
50static void apply_second_mode_setting(struct fb_var_screeninfo
51 *sec_var);
52static void retrieve_device_setting(struct viafb_ioctl_setting
53 *setting_info);
54static void viafb_set_video_device(u32 video_dev_info);
55static void viafb_get_video_device(u32 *video_dev_info);
56
57/* Mode information */
58static const struct viafb_modeinfo viafb_modentry[] = {
59 {480, 640, VIA_RES_480X640, "480x640"},
60 {640, 480, VIA_RES_640X480, "640x480"},
61 {800, 480, VIA_RES_800X480, "800x480"},
62 {800, 600, VIA_RES_800X600, "800x600"},
63 {1024, 768, VIA_RES_1024X768, "1024x768"},
64 {1152, 864, VIA_RES_1152X864, "1152x864"},
65 {1280, 1024, VIA_RES_1280X1024, "1280x1024"},
66 {1600, 1200, VIA_RES_1600X1200, "1600x1200"},
67 {1440, 1050, VIA_RES_1440X1050, "1440x1050"},
68 {1280, 768, VIA_RES_1280X768, "1280x768"},
69 {1280, 800, VIA_RES_1280X800, "1280x800"},
70 {1280, 960, VIA_RES_1280X960, "1280x960"},
71 {1920, 1440, VIA_RES_1920X1440, "1920x1440"},
72 {848, 480, VIA_RES_848X480, "848x480"},
73 {1400, 1050, VIA_RES_1400X1050, "1400x1050"},
74 {720, 480, VIA_RES_720X480, "720x480"},
75 {720, 576, VIA_RES_720X576, "720x576"},
76 {1024, 512, VIA_RES_1024X512, "1024x512"},
77 {1024, 576, VIA_RES_1024X576, "1024x576"},
78 {1024, 600, VIA_RES_1024X600, "1024x600"},
79 {1280, 720, VIA_RES_1280X720, "1280x720"},
80 {1920, 1080, VIA_RES_1920X1080, "1920x1080"},
81 {1366, 768, VIA_RES_1368X768, "1368x768"},
82 {1680, 1050, VIA_RES_1680X1050, "1680x1050"},
83 {960, 600, VIA_RES_960X600, "960x600"},
84 {1000, 600, VIA_RES_1000X600, "1000x600"},
85 {1024, 576, VIA_RES_1024X576, "1024x576"},
86 {1024, 600, VIA_RES_1024X600, "1024x600"},
87 {1088, 612, VIA_RES_1088X612, "1088x612"},
88 {1152, 720, VIA_RES_1152X720, "1152x720"},
89 {1200, 720, VIA_RES_1200X720, "1200x720"},
90 {1280, 600, VIA_RES_1280X600, "1280x600"},
91 {1360, 768, VIA_RES_1360X768, "1360x768"},
92 {1440, 900, VIA_RES_1440X900, "1440x900"},
93 {1600, 900, VIA_RES_1600X900, "1600x900"},
94 {1600, 1024, VIA_RES_1600X1024, "1600x1024"},
95 {1792, 1344, VIA_RES_1792X1344, "1792x1344"},
96 {1856, 1392, VIA_RES_1856X1392, "1856x1392"},
97 {1920, 1200, VIA_RES_1920X1200, "1920x1200"},
98 {2048, 1536, VIA_RES_2048X1536, "2048x1536"},
99 {0, 0, VIA_RES_INVALID, "640x480"}
100};
101
102static struct fb_ops viafb_ops;
103
104static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
105{
106 struct viafb_par *ppar;
107 ppar = info->par;
108
109 DEBUG_MSG(KERN_INFO "viafb_update_fix!\n");
110
111 fix->visual =
112 ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
113 fix->line_length = ppar->linelength;
114
115 return 0;
116}
117
118
119static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
120 struct viafb_par *viaparinfo)
121{
122 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
123 strcpy(fix->id, viafb_name);
124
125 fix->smem_start = viaparinfo->fbmem;
126 fix->smem_len = viaparinfo->fbmem_free;
127 fix->mmio_start = viaparinfo->mmio_base;
128 fix->mmio_len = viaparinfo->mmio_len;
129
130 fix->type = FB_TYPE_PACKED_PIXELS;
131 fix->type_aux = 0;
132
133 fix->xpanstep = fix->ywrapstep = 0;
134 fix->ypanstep = 1;
135
136 /* Just tell the accel name */
137 viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
138}
139static int viafb_open(struct fb_info *info, int user)
140{
141 DEBUG_MSG(KERN_INFO "viafb_open!\n");
142 return 0;
143}
144
145static int viafb_release(struct fb_info *info, int user)
146{
147 DEBUG_MSG(KERN_INFO "viafb_release!\n");
148 return 0;
149}
150
151static void viafb_update_viafb_par(struct fb_info *info)
152{
153 struct viafb_par *ppar;
154
155 ppar = info->par;
156 ppar->bpp = info->var.bits_per_pixel;
157 ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8;
158 ppar->hres = info->var.xres;
159 ppar->vres = info->var.yres;
160 ppar->xoffset = info->var.xoffset;
161 ppar->yoffset = info->var.yoffset;
162}
163
164static int viafb_check_var(struct fb_var_screeninfo *var,
165 struct fb_info *info)
166{
167 int vmode_index, htotal, vtotal;
168 struct viafb_par *ppar;
169 u32 long_refresh;
170 struct viafb_par *p_viafb_par;
171 ppar = info->par;
172
173
174 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
175 /* Sanity check */
176 /* HW neither support interlacte nor double-scaned mode */
177 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
178 return -EINVAL;
179
180 vmode_index = viafb_get_mode_index(var->xres, var->yres, 0);
181 if (vmode_index == VIA_RES_INVALID) {
182 DEBUG_MSG(KERN_INFO
183 "viafb: Mode %dx%dx%d not supported!!\n",
184 var->xres, var->yres, var->bits_per_pixel);
185 return -EINVAL;
186 }
187
188 if (24 == var->bits_per_pixel)
189 var->bits_per_pixel = 32;
190
191 if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
192 var->bits_per_pixel != 32)
193 return -EINVAL;
194
195 if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
196 /*32 pixel alignment */
197 var->xres_virtual = (var->xres_virtual + 31) & ~31;
198 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
199 ppar->memsize)
200 return -EINVAL;
201
202 /* Based on var passed in to calculate the refresh,
203 * because our driver use some modes special.
204 */
205 htotal = var->xres + var->left_margin +
206 var->right_margin + var->hsync_len;
207 vtotal = var->yres + var->upper_margin +
208 var->lower_margin + var->vsync_len;
209 long_refresh = 1000000000UL / var->pixclock * 1000;
210 long_refresh /= (htotal * vtotal);
211
212 viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
213
214 /* Adjust var according to our driver's own table */
215 viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
216
217 /* This is indeed a patch for VT3353 */
218 if (!info->par)
219 return -1;
220 p_viafb_par = (struct viafb_par *)info->par;
221 if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800)
222 var->accel_flags = 0;
223
224 return 0;
225}
226
227static int viafb_set_par(struct fb_info *info)
228{
229 int vmode_index;
230 int vmode_index1 = 0;
231 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
232
233 viafb_update_device_setting(info->var.xres, info->var.yres,
234 info->var.bits_per_pixel, viafb_refresh, 0);
235
236 vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0);
237
238 if (viafb_SAMM_ON == 1) {
239 DEBUG_MSG(KERN_INFO
240 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
241 viafb_second_xres, viafb_second_yres, viafb_bpp1);
242 vmode_index1 = viafb_get_mode_index(viafb_second_xres,
243 viafb_second_yres, 1);
244 DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
245 vmode_index1);
246
247 viafb_update_device_setting(viafb_second_xres,
248 viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
249 }
250
251 if (vmode_index != VIA_RES_INVALID) {
252 viafb_setmode(vmode_index, info->var.xres, info->var.yres,
253 info->var.bits_per_pixel, vmode_index1,
254 viafb_second_xres, viafb_second_yres, viafb_bpp1);
255
256 /*We should set memory offset according virtual_x */
257 /*Fix me:put this function into viafb_setmode */
258 viafb_memory_pitch_patch(info);
259
260 /* Update ***fb_par information */
261 viafb_update_viafb_par(info);
262
263 /* Update other fixed information */
264 viafb_update_fix(&info->fix, info);
265 viafb_bpp = info->var.bits_per_pixel;
266 /* Update viafb_accel, it is necessary to our 2D accelerate */
267 viafb_accel = info->var.accel_flags;
268
269 if (viafb_accel)
270 viafb_set_2d_color_depth(info->var.bits_per_pixel);
271 }
272
273 return 0;
274}
275
276/* Set one color register */
277static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
278unsigned blue, unsigned transp, struct fb_info *info)
279{
280 u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
281 unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
282 DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
283 if (regno >= cmap_entries)
284 return 1;
285 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
286 /*
287 * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
288 */
289 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
290 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
291 }
292 switch (info->var.bits_per_pixel) {
293 case 8:
294 outb(0x1A, 0x3C4);
295 sr1a = inb(0x3C5);
296 outb(0x1B, 0x3C4);
297 sr1b = inb(0x3C5);
298 outb(0x67, 0x3D4);
299 cr67 = inb(0x3D5);
300 outb(0x6A, 0x3D4);
301 cr6a = inb(0x3D5);
302
303 /* Map the 3C6/7/8/9 to the IGA2 */
304 outb(0x1A, 0x3C4);
305 outb(sr1a | 0x01, 0x3C5);
306 /* Second Display Engine colck always on */
307 outb(0x1B, 0x3C4);
308 outb(sr1b | 0x80, 0x3C5);
309 /* Second Display Color Depth 8 */
310 outb(0x67, 0x3D4);
311 outb(cr67 & 0x3F, 0x3D5);
312 outb(0x6A, 0x3D4);
313 /* Second Display Channel Reset CR6A[6]) */
314 outb(cr6a & 0xBF, 0x3D5);
315 /* Second Display Channel Enable CR6A[7] */
316 outb(cr6a | 0x80, 0x3D5);
317 /* Second Display Channel stop reset) */
318 outb(cr6a | 0x40, 0x3D5);
319
320 /* Bit mask of palette */
321 outb(0xFF, 0x3c6);
322 /* Write one register of IGA2 */
323 outb(regno, 0x3C8);
324 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
325 rev >= 15) {
326 shift = 8;
327 viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
328 viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
329 } else {
330 shift = 10;
331 viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
332 viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
333 }
334 outb(red >> shift, 0x3C9);
335 outb(green >> shift, 0x3C9);
336 outb(blue >> shift, 0x3C9);
337
338 /* Map the 3C6/7/8/9 to the IGA1 */
339 outb(0x1A, 0x3C4);
340 outb(sr1a & 0xFE, 0x3C5);
341 /* Bit mask of palette */
342 outb(0xFF, 0x3c6);
343 /* Write one register of IGA1 */
344 outb(regno, 0x3C8);
345 outb(red >> shift, 0x3C9);
346 outb(green >> shift, 0x3C9);
347 outb(blue >> shift, 0x3C9);
348
349 outb(0x1A, 0x3C4);
350 outb(sr1a, 0x3C5);
351 outb(0x1B, 0x3C4);
352 outb(sr1b, 0x3C5);
353 outb(0x67, 0x3D4);
354 outb(cr67, 0x3D5);
355 outb(0x6A, 0x3D4);
356 outb(cr6a, 0x3D5);
357 break;
358 case 16:
359 ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
360 ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
361 break;
362 case 32:
363 ((u32 *) info->pseudo_palette)[regno] =
364 ((transp & 0xFF00) << 16) |
365 ((red & 0xFF00) << 8) |
366 ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
367 break;
368 }
369
370 return 0;
371
372}
373
374/*CALLED BY: fb_set_cmap */
375/* fb_set_var, pass 256 colors */
376/*CALLED BY: fb_set_cmap */
377/* fbcon_set_palette, pass 16 colors */
378static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
379{
380 u32 len = cmap->len;
381 u32 i;
382 u16 *pred = cmap->red;
383 u16 *pgreen = cmap->green;
384 u16 *pblue = cmap->blue;
385 u16 *ptransp = cmap->transp;
386 u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
387 if (len > 256)
388 return 1;
389 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
390 /*
391 * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
392 * rev.
393 */
394 outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
395 rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
396 }
397 switch (info->var.bits_per_pixel) {
398 case 8:
399 outb(0x1A, 0x3C4);
400 sr1a = inb(0x3C5);
401 outb(0x1B, 0x3C4);
402 sr1b = inb(0x3C5);
403 outb(0x67, 0x3D4);
404 cr67 = inb(0x3D5);
405 outb(0x6A, 0x3D4);
406 cr6a = inb(0x3D5);
407 /* Map the 3C6/7/8/9 to the IGA2 */
408 outb(0x1A, 0x3C4);
409 outb(sr1a | 0x01, 0x3C5);
410 outb(0x1B, 0x3C4);
411 /* Second Display Engine colck always on */
412 outb(sr1b | 0x80, 0x3C5);
413 outb(0x67, 0x3D4);
414 /* Second Display Color Depth 8 */
415 outb(cr67 & 0x3F, 0x3D5);
416 outb(0x6A, 0x3D4);
417 /* Second Display Channel Reset CR6A[6]) */
418 outb(cr6a & 0xBF, 0x3D5);
419 /* Second Display Channel Enable CR6A[7] */
420 outb(cr6a | 0x80, 0x3D5);
421 /* Second Display Channel stop reset) */
422 outb(cr6a | 0xC0, 0x3D5);
423
424 /* Bit mask of palette */
425 outb(0xFF, 0x3c6);
426 outb(0x00, 0x3C8);
427 if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
428 rev >= 15) {
429 shift = 8;
430 viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
431 viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
432 } else {
433 shift = 10;
434 viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
435 viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
436 }
437 for (i = 0; i < len; i++) {
438 outb((*(pred + i)) >> shift, 0x3C9);
439 outb((*(pgreen + i)) >> shift, 0x3C9);
440 outb((*(pblue + i)) >> shift, 0x3C9);
441 }
442
443 outb(0x1A, 0x3C4);
444 /* Map the 3C6/7/8/9 to the IGA1 */
445 outb(sr1a & 0xFE, 0x3C5);
446 /* Bit mask of palette */
447 outb(0xFF, 0x3c6);
448 outb(0x00, 0x3C8);
449 for (i = 0; i < len; i++) {
450 outb((*(pred + i)) >> shift, 0x3C9);
451 outb((*(pgreen + i)) >> shift, 0x3C9);
452 outb((*(pblue + i)) >> shift, 0x3C9);
453 }
454
455 outb(0x1A, 0x3C4);
456 outb(sr1a, 0x3C5);
457 outb(0x1B, 0x3C4);
458 outb(sr1b, 0x3C5);
459 outb(0x67, 0x3D4);
460 outb(cr67, 0x3D5);
461 outb(0x6A, 0x3D4);
462 outb(cr6a, 0x3D5);
463 break;
464 case 16:
465 if (len > 17)
466 return 0; /* Because static u32 pseudo_pal[17]; */
467 for (i = 0; i < len; i++)
468 ((u32 *) info->pseudo_palette)[i] =
469 (*(pred + i) & 0xF800) |
470 ((*(pgreen + i) & 0xFC00) >> 5) |
471 ((*(pblue + i) & 0xF800) >> 11);
472 break;
473 case 32:
474 if (len > 17)
475 return 0;
476 if (ptransp) {
477 for (i = 0; i < len; i++)
478 ((u32 *) info->pseudo_palette)[i] =
479 ((*(ptransp + i) & 0xFF00) << 16) |
480 ((*(pred + i) & 0xFF00) << 8) |
481 ((*(pgreen + i) & 0xFF00)) |
482 ((*(pblue + i) & 0xFF00) >> 8);
483 } else {
484 for (i = 0; i < len; i++)
485 ((u32 *) info->pseudo_palette)[i] =
486 0x00000000 |
487 ((*(pred + i) & 0xFF00) << 8) |
488 ((*(pgreen + i) & 0xFF00)) |
489 ((*(pblue + i) & 0xFF00) >> 8);
490 }
491 break;
492 }
493 return 0;
494}
495
496static int viafb_pan_display(struct fb_var_screeninfo *var,
497 struct fb_info *info)
498{
499 unsigned int offset;
500
501 DEBUG_MSG(KERN_INFO "viafb_pan_display!\n");
502
503 offset = (var->xoffset + (var->yoffset * var->xres_virtual)) *
504 var->bits_per_pixel / 16;
505
506 DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
507
508 viafb_write_reg_mask(0x48, 0x3d4, ((offset >> 24) & 0x3), 0x3);
509 viafb_write_reg_mask(0x34, 0x3d4, ((offset >> 16) & 0xff), 0xff);
510 viafb_write_reg_mask(0x0c, 0x3d4, ((offset >> 8) & 0xff), 0xff);
511 viafb_write_reg_mask(0x0d, 0x3d4, (offset & 0xff), 0xff);
512
513 return 0;
514}
515
516static int viafb_blank(int blank_mode, struct fb_info *info)
517{
518 DEBUG_MSG(KERN_INFO "viafb_blank!\n");
519 /* clear DPMS setting */
520
521 switch (blank_mode) {
522 case FB_BLANK_UNBLANK:
523 /* Screen: On, HSync: On, VSync: On */
524 /* control CRT monitor power management */
525 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
526 break;
527 case FB_BLANK_HSYNC_SUSPEND:
528 /* Screen: Off, HSync: Off, VSync: On */
529 /* control CRT monitor power management */
530 viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
531 break;
532 case FB_BLANK_VSYNC_SUSPEND:
533 /* Screen: Off, HSync: On, VSync: Off */
534 /* control CRT monitor power management */
535 viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
536 break;
537 case FB_BLANK_POWERDOWN:
538 /* Screen: Off, HSync: Off, VSync: Off */
539 /* control CRT monitor power management */
540 viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
541 break;
542 }
543
544 return 0;
545}
546
547static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
548{
549 struct viafb_ioctl_mode viamode;
550 struct viafb_ioctl_samm viasamm;
551 struct viafb_driver_version driver_version;
552 struct fb_var_screeninfo sec_var;
553 struct _panel_size_pos_info panel_pos_size_para;
554 u32 state_info = 0;
555 u32 viainfo_size = sizeof(struct viafb_ioctl_info);
556 u32 *viafb_gamma_table;
557 char driver_name[] = "viafb";
558
559 u32 __user *argp = (u32 __user *) arg;
560 u32 gpu32;
561 u32 video_dev_info = 0;
562 struct viafb_ioctl_setting viafb_setting = {};
563 struct device_t active_dev = {};
564
565 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
566
567 switch (cmd) {
568 case VIAFB_GET_CHIP_INFO:
569 if (copy_to_user(argp, viaparinfo->chip_info,
570 sizeof(struct chip_information)))
571 return -EFAULT;
572 break;
573 case VIAFB_GET_INFO_SIZE:
574 return put_user(viainfo_size, argp);
575 case VIAFB_GET_INFO:
576 return viafb_ioctl_get_viafb_info(arg);
577 case VIAFB_HOTPLUG:
578 return put_user(viafb_ioctl_hotplug(info->var.xres,
579 info->var.yres,
580 info->var.bits_per_pixel), argp);
581 case VIAFB_SET_HOTPLUG_FLAG:
582 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
583 return -EFAULT;
584 viafb_hotplug = (gpu32) ? 1 : 0;
585 break;
586 case VIAFB_GET_RESOLUTION:
587 viamode.xres = (u32) viafb_hotplug_Xres;
588 viamode.yres = (u32) viafb_hotplug_Yres;
589 viamode.refresh = (u32) viafb_hotplug_refresh;
590 viamode.bpp = (u32) viafb_hotplug_bpp;
591 if (viafb_SAMM_ON == 1) {
592 viamode.xres_sec = viafb_second_xres;
593 viamode.yres_sec = viafb_second_yres;
594 viamode.virtual_xres_sec = viafb_second_virtual_xres;
595 viamode.virtual_yres_sec = viafb_second_virtual_yres;
596 viamode.refresh_sec = viafb_refresh1;
597 viamode.bpp_sec = viafb_bpp1;
598 } else {
599 viamode.xres_sec = 0;
600 viamode.yres_sec = 0;
601 viamode.virtual_xres_sec = 0;
602 viamode.virtual_yres_sec = 0;
603 viamode.refresh_sec = 0;
604 viamode.bpp_sec = 0;
605 }
606 if (copy_to_user(argp, &viamode, sizeof(viamode)))
607 return -EFAULT;
608 break;
609 case VIAFB_GET_SAMM_INFO:
610 viasamm.samm_status = viafb_SAMM_ON;
611
612 if (viafb_SAMM_ON == 1) {
613 if (viafb_dual_fb) {
614 viasamm.size_prim = viaparinfo->fbmem_free;
615 viasamm.size_sec = viaparinfo1->fbmem_free;
616 } else {
617 if (viafb_second_size) {
618 viasamm.size_prim =
619 viaparinfo->fbmem_free -
620 viafb_second_size * 1024 * 1024;
621 viasamm.size_sec =
622 viafb_second_size * 1024 * 1024;
623 } else {
624 viasamm.size_prim =
625 viaparinfo->fbmem_free >> 1;
626 viasamm.size_sec =
627 (viaparinfo->fbmem_free >> 1);
628 }
629 }
630 viasamm.mem_base = viaparinfo->fbmem;
631 viasamm.offset_sec = viafb_second_offset;
632 } else {
633 viasamm.size_prim =
634 viaparinfo->memsize - viaparinfo->fbmem_used;
635 viasamm.size_sec = 0;
636 viasamm.mem_base = viaparinfo->fbmem;
637 viasamm.offset_sec = 0;
638 }
639
640 if (copy_to_user(argp, &viasamm, sizeof(viasamm)))
641 return -EFAULT;
642
643 break;
644 case VIAFB_TURN_ON_OUTPUT_DEVICE:
645 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
646 return -EFAULT;
647 if (gpu32 & CRT_Device)
648 viafb_crt_enable();
649 if (gpu32 & DVI_Device)
650 viafb_dvi_enable();
651 if (gpu32 & LCD_Device)
652 viafb_lcd_enable();
653 break;
654 case VIAFB_TURN_OFF_OUTPUT_DEVICE:
655 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
656 return -EFAULT;
657 if (gpu32 & CRT_Device)
658 viafb_crt_disable();
659 if (gpu32 & DVI_Device)
660 viafb_dvi_disable();
661 if (gpu32 & LCD_Device)
662 viafb_lcd_disable();
663 break;
664 case VIAFB_SET_DEVICE:
665 if (copy_from_user(&active_dev, (void *)argp,
666 sizeof(active_dev)))
667 return -EFAULT;
668 viafb_set_device(active_dev);
669 viafb_set_par(info);
670 break;
671 case VIAFB_GET_DEVICE:
672 active_dev.crt = viafb_CRT_ON;
673 active_dev.dvi = viafb_DVI_ON;
674 active_dev.lcd = viafb_LCD_ON;
675 active_dev.samm = viafb_SAMM_ON;
676 active_dev.primary_dev = viafb_primary_dev;
677
678 active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
679 active_dev.lcd_panel_id = viafb_lcd_panel_id;
680 active_dev.lcd_mode = viafb_lcd_mode;
681
682 active_dev.xres = viafb_hotplug_Xres;
683 active_dev.yres = viafb_hotplug_Yres;
684
685 active_dev.xres1 = viafb_second_xres;
686 active_dev.yres1 = viafb_second_yres;
687
688 active_dev.bpp = viafb_bpp;
689 active_dev.bpp1 = viafb_bpp1;
690 active_dev.refresh = viafb_refresh;
691 active_dev.refresh1 = viafb_refresh1;
692
693 active_dev.epia_dvi = viafb_platform_epia_dvi;
694 active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
695 active_dev.bus_width = viafb_bus_width;
696
697 if (copy_to_user(argp, &active_dev, sizeof(active_dev)))
698 return -EFAULT;
699 break;
700
701 case VIAFB_GET_DRIVER_VERSION:
702 driver_version.iMajorNum = VERSION_MAJOR;
703 driver_version.iKernelNum = VERSION_KERNEL;
704 driver_version.iOSNum = VERSION_OS;
705 driver_version.iMinorNum = VERSION_MINOR;
706
707 if (copy_to_user(argp, &driver_version,
708 sizeof(driver_version)))
709 return -EFAULT;
710
711 break;
712
713 case VIAFB_SET_DEVICE_INFO:
714 if (copy_from_user(&viafb_setting,
715 argp, sizeof(viafb_setting)))
716 return -EFAULT;
717 if (apply_device_setting(viafb_setting, info) < 0)
718 return -EINVAL;
719
720 break;
721
722 case VIAFB_SET_SECOND_MODE:
723 if (copy_from_user(&sec_var, argp, sizeof(sec_var)))
724 return -EFAULT;
725 apply_second_mode_setting(&sec_var);
726 break;
727
728 case VIAFB_GET_DEVICE_INFO:
729
730 retrieve_device_setting(&viafb_setting);
731
732 if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting)))
733 return -EFAULT;
734
735 break;
736
737 case VIAFB_GET_DEVICE_SUPPORT:
738 viafb_get_device_support_state(&state_info);
739 if (put_user(state_info, argp))
740 return -EFAULT;
741 break;
742
743 case VIAFB_GET_DEVICE_CONNECT:
744 viafb_get_device_connect_state(&state_info);
745 if (put_user(state_info, argp))
746 return -EFAULT;
747 break;
748
749 case VIAFB_GET_PANEL_SUPPORT_EXPAND:
750 state_info =
751 viafb_lcd_get_support_expand_state(info->var.xres,
752 info->var.yres);
753 if (put_user(state_info, argp))
754 return -EFAULT;
755 break;
756
757 case VIAFB_GET_DRIVER_NAME:
758 if (copy_to_user(argp, driver_name, sizeof(driver_name)))
759 return -EFAULT;
760 break;
761
762 case VIAFB_SET_GAMMA_LUT:
763 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
764 if (!viafb_gamma_table)
765 return -ENOMEM;
766 if (copy_from_user(viafb_gamma_table, argp,
767 sizeof(viafb_gamma_table))) {
768 kfree(viafb_gamma_table);
769 return -EFAULT;
770 }
771 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
772 kfree(viafb_gamma_table);
773 break;
774
775 case VIAFB_GET_GAMMA_LUT:
776 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
777 if (!viafb_gamma_table)
778 return -ENOMEM;
779 viafb_get_gamma_table(viafb_gamma_table);
780 if (copy_to_user(argp, viafb_gamma_table,
781 sizeof(viafb_gamma_table))) {
782 kfree(viafb_gamma_table);
783 return -EFAULT;
784 }
785 kfree(viafb_gamma_table);
786 break;
787
788 case VIAFB_GET_GAMMA_SUPPORT_STATE:
789 viafb_get_gamma_support_state(viafb_bpp, &state_info);
790 if (put_user(state_info, argp))
791 return -EFAULT;
792 break;
793 case VIAFB_SET_VIDEO_DEVICE:
794 get_user(video_dev_info, argp);
795 viafb_set_video_device(video_dev_info);
796 break;
797 case VIAFB_GET_VIDEO_DEVICE:
798 viafb_get_video_device(&video_dev_info);
799 if (put_user(video_dev_info, argp))
800 return -EFAULT;
801 break;
802 case VIAFB_SYNC_SURFACE:
803 DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
804 break;
805 case VIAFB_GET_DRIVER_CAPS:
806 break;
807
808 case VIAFB_GET_PANEL_MAX_SIZE:
809 if (copy_from_user
810 (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
811 return -EFAULT;
812 panel_pos_size_para.x = panel_pos_size_para.y = 0;
813 if (copy_to_user(argp, &panel_pos_size_para,
814 sizeof(panel_pos_size_para)))
815 return -EFAULT;
816 break;
817 case VIAFB_GET_PANEL_MAX_POSITION:
818 if (copy_from_user
819 (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
820 return -EFAULT;
821 panel_pos_size_para.x = panel_pos_size_para.y = 0;
822 if (copy_to_user(argp, &panel_pos_size_para,
823 sizeof(panel_pos_size_para)))
824 return -EFAULT;
825 break;
826
827 case VIAFB_GET_PANEL_POSITION:
828 if (copy_from_user
829 (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
830 return -EFAULT;
831 panel_pos_size_para.x = panel_pos_size_para.y = 0;
832 if (copy_to_user(argp, &panel_pos_size_para,
833 sizeof(panel_pos_size_para)))
834 return -EFAULT;
835 break;
836 case VIAFB_GET_PANEL_SIZE:
837 if (copy_from_user
838 (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
839 return -EFAULT;
840 panel_pos_size_para.x = panel_pos_size_para.y = 0;
841 if (copy_to_user(argp, &panel_pos_size_para,
842 sizeof(panel_pos_size_para)))
843 return -EFAULT;
844 break;
845
846 case VIAFB_SET_PANEL_POSITION:
847 if (copy_from_user
848 (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
849 return -EFAULT;
850 break;
851 case VIAFB_SET_PANEL_SIZE:
852 if (copy_from_user
853 (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
854 return -EFAULT;
855 break;
856
857 default:
858 return -EINVAL;
859 }
860
861 return 0;
862}
863
864static void viafb_fillrect(struct fb_info *info,
865 const struct fb_fillrect *rect)
866{
867 u32 col = 0, rop = 0;
868 int pitch;
869
870 if (!viafb_accel)
871 return cfb_fillrect(info, rect);
872
873 if (!rect->width || !rect->height)
874 return;
875
876 switch (rect->rop) {
877 case ROP_XOR:
878 rop = 0x5A;
879 break;
880 case ROP_COPY:
881 default:
882 rop = 0xF0;
883 break;
884 }
885
886 switch (info->var.bits_per_pixel) {
887 case 8:
888 col = rect->color;
889 break;
890 case 16:
891 col = ((u32 *) (info->pseudo_palette))[rect->color];
892 break;
893 case 32:
894 col = ((u32 *) (info->pseudo_palette))[rect->color];
895 break;
896 }
897
898 /* BitBlt Source Address */
899 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
900 /* Source Base Address */
901 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
902 /* Destination Base Address */
903 writel(((unsigned long) (info->screen_base) -
904 (unsigned long) viafb_FB_MM) >> 3,
905 viaparinfo->io_virt + VIA_REG_DSTBASE);
906 /* Pitch */
907 pitch = (info->var.xres_virtual + 7) & ~7;
908 writel(VIA_PITCH_ENABLE |
909 (((pitch *
910 info->var.bits_per_pixel >> 3) >> 3) |
911 (((pitch * info->
912 var.bits_per_pixel >> 3) >> 3) << 16)),
913 viaparinfo->io_virt + VIA_REG_PITCH);
914 /* BitBlt Destination Address */
915 writel(((rect->dy << 16) | rect->dx),
916 viaparinfo->io_virt + VIA_REG_DSTPOS);
917 /* Dimension: width & height */
918 writel((((rect->height - 1) << 16) | (rect->width - 1)),
919 viaparinfo->io_virt + VIA_REG_DIMENSION);
920 /* Forground color or Destination color */
921 writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
922 /* GE Command */
923 writel((0x01 | 0x2000 | (rop << 24)),
924 viaparinfo->io_virt + VIA_REG_GECMD);
925
926}
927
928static void viafb_copyarea(struct fb_info *info,
929 const struct fb_copyarea *area)
930{
931 u32 dy = area->dy, sy = area->sy, direction = 0x0;
932 u32 sx = area->sx, dx = area->dx, width = area->width;
933 int pitch;
934
935 DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n");
936
937 if (!viafb_accel)
938 return cfb_copyarea(info, area);
939
940 if (!area->width || !area->height)
941 return;
942
943 if (sy < dy) {
944 dy += area->height - 1;
945 sy += area->height - 1;
946 direction |= 0x4000;
947 }
948
949 if (sx < dx) {
950 dx += width - 1;
951 sx += width - 1;
952 direction |= 0x8000;
953 }
954
955 /* Source Base Address */
956 writel(((unsigned long) (info->screen_base) -
957 (unsigned long) viafb_FB_MM) >> 3,
958 viaparinfo->io_virt + VIA_REG_SRCBASE);
959 /* Destination Base Address */
960 writel(((unsigned long) (info->screen_base) -
961 (unsigned long) viafb_FB_MM) >> 3,
962 viaparinfo->io_virt + VIA_REG_DSTBASE);
963 /* Pitch */
964 pitch = (info->var.xres_virtual + 7) & ~7;
965 /* VIA_PITCH_ENABLE can be omitted now. */
966 writel(VIA_PITCH_ENABLE |
967 (((pitch *
968 info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
969 info->var.
970 bits_per_pixel
971 >> 3) >> 3)
972 << 16)),
973 viaparinfo->io_virt + VIA_REG_PITCH);
974 /* BitBlt Source Address */
975 writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS);
976 /* BitBlt Destination Address */
977 writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS);
978 /* Dimension: width & height */
979 writel((((area->height - 1) << 16) | (area->width - 1)),
980 viaparinfo->io_virt + VIA_REG_DIMENSION);
981 /* GE Command */
982 writel((0x01 | direction | (0xCC << 24)),
983 viaparinfo->io_virt + VIA_REG_GECMD);
984
985}
986
987static void viafb_imageblit(struct fb_info *info,
988 const struct fb_image *image)
989{
990 u32 size, bg_col = 0, fg_col = 0, *udata;
991 int i;
992 int pitch;
993
994 if (!viafb_accel)
995 return cfb_imageblit(info, image);
996
997 udata = (u32 *) image->data;
998
999 switch (info->var.bits_per_pixel) {
1000 case 8:
1001 bg_col = image->bg_color;
1002 fg_col = image->fg_color;
1003 break;
1004 case 16:
1005 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
1006 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
1007 break;
1008 case 32:
1009 bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
1010 fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
1011 break;
1012 }
1013 size = image->width * image->height;
1014
1015 /* Source Base Address */
1016 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
1017 /* Destination Base Address */
1018 writel(((unsigned long) (info->screen_base) -
1019 (unsigned long) viafb_FB_MM) >> 3,
1020 viaparinfo->io_virt + VIA_REG_DSTBASE);
1021 /* Pitch */
1022 pitch = (info->var.xres_virtual + 7) & ~7;
1023 writel(VIA_PITCH_ENABLE |
1024 (((pitch *
1025 info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
1026 info->var.
1027 bits_per_pixel
1028 >> 3) >> 3)
1029 << 16)),
1030 viaparinfo->io_virt + VIA_REG_PITCH);
1031 /* BitBlt Source Address */
1032 writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
1033 /* BitBlt Destination Address */
1034 writel(((image->dy << 16) | image->dx),
1035 viaparinfo->io_virt + VIA_REG_DSTPOS);
1036 /* Dimension: width & height */
1037 writel((((image->height - 1) << 16) | (image->width - 1)),
1038 viaparinfo->io_virt + VIA_REG_DIMENSION);
1039 /* fb color */
1040 writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
1041 /* bg color */
1042 writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR);
1043 /* GE Command */
1044 writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD);
1045
1046 for (i = 0; i < size / 4; i++) {
1047 writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE);
1048 udata++;
1049 }
1050
1051}
1052
1053static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1054{
1055 u8 data[CURSOR_SIZE / 8];
1056 u32 data_bak[CURSOR_SIZE / 32];
1057 u32 temp, xx, yy, bg_col = 0, fg_col = 0;
1058 int size, i, j = 0;
1059 static int hw_cursor;
1060 struct viafb_par *p_viafb_par;
1061
1062 if (viafb_accel)
1063 hw_cursor = 1;
1064
1065 if (!viafb_accel) {
1066 if (hw_cursor) {
1067 viafb_show_hw_cursor(info, HW_Cursor_OFF);
1068 hw_cursor = 0;
1069 }
1070 return -ENODEV;
1071 }
1072
1073 if ((((struct viafb_par *)(info->par))->iga_path == IGA2)
1074 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
1075 return -ENODEV;
1076
1077 /* When duoview and using lcd , use soft cursor */
1078 if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview)
1079 return -ENODEV;
1080
1081 viafb_show_hw_cursor(info, HW_Cursor_OFF);
1082 viacursor = *cursor;
1083
1084 if (cursor->set & FB_CUR_SETHOT) {
1085 viacursor.hot = cursor->hot;
1086 temp = ((viacursor.hot.x) << 16) + viacursor.hot.y;
1087 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
1088 }
1089
1090 if (cursor->set & FB_CUR_SETPOS) {
1091 viacursor.image.dx = cursor->image.dx;
1092 viacursor.image.dy = cursor->image.dy;
1093 yy = cursor->image.dy - info->var.yoffset;
1094 xx = cursor->image.dx - info->var.xoffset;
1095 temp = yy & 0xFFFF;
1096 temp |= (xx << 16);
1097 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
1098 }
1099
1100 if (cursor->set & FB_CUR_SETSIZE) {
1101 temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
1102
1103 if ((cursor->image.width <= 32)
1104 && (cursor->image.height <= 32)) {
1105 MAX_CURS = 32;
1106 temp |= 0x2;
1107 } else if ((cursor->image.width <= 64)
1108 && (cursor->image.height <= 64)) {
1109 MAX_CURS = 64;
1110 temp &= 0xFFFFFFFD;
1111 } else {
1112 DEBUG_MSG(KERN_INFO
1113 "The cursor image is biger than 64x64 bits...\n");
1114 return -ENXIO;
1115 }
1116 writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
1117
1118 viacursor.image.height = cursor->image.height;
1119 viacursor.image.width = cursor->image.width;
1120 }
1121
1122 if (cursor->set & FB_CUR_SETCMAP) {
1123 viacursor.image.fg_color = cursor->image.fg_color;
1124 viacursor.image.bg_color = cursor->image.bg_color;
1125
1126 switch (info->var.bits_per_pixel) {
1127 case 8:
1128 case 16:
1129 case 32:
1130 bg_col =
1131 (0xFF << 24) |
1132 (((info->cmap.red)[viacursor.image.bg_color] &
1133 0xFF00) << 8) |
1134 ((info->cmap.green)[viacursor.image.bg_color] &
1135 0xFF00) |
1136 (((info->cmap.blue)[viacursor.image.bg_color] &
1137 0xFF00) >> 8);
1138 fg_col =
1139 (0xFF << 24) |
1140 (((info->cmap.red)[viacursor.image.fg_color] &
1141 0xFF00) << 8) |
1142 ((info->cmap.green)[viacursor.image.fg_color] &
1143 0xFF00) |
1144 (((info->cmap.blue)[viacursor.image.fg_color] &
1145 0xFF00) >> 8);
1146 break;
1147 default:
1148 return 0;
1149 }
1150
1151 /* This is indeed a patch for VT3324/VT3353 */
1152 if (!info->par)
1153 return 0;
1154 p_viafb_par = (struct viafb_par *)info->par;
1155
1156 if ((p_viafb_par->chip_info->gfx_chip_name ==
1157 UNICHROME_CX700) ||
1158 ((p_viafb_par->chip_info->gfx_chip_name ==
1159 UNICHROME_VX800))) {
1160 bg_col =
1161 (((info->cmap.red)[viacursor.image.bg_color] &
1162 0xFFC0) << 14) |
1163 (((info->cmap.green)[viacursor.image.bg_color] &
1164 0xFFC0) << 4) |
1165 (((info->cmap.blue)[viacursor.image.bg_color] &
1166 0xFFC0) >> 6);
1167 fg_col =
1168 (((info->cmap.red)[viacursor.image.fg_color] &
1169 0xFFC0) << 14) |
1170 (((info->cmap.green)[viacursor.image.fg_color] &
1171 0xFFC0) << 4) |
1172 (((info->cmap.blue)[viacursor.image.fg_color] &
1173 0xFFC0) >> 6);
1174 }
1175
1176 writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
1177 writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
1178 }
1179
1180 if (cursor->set & FB_CUR_SETSHAPE) {
1181 size =
1182 ((viacursor.image.width + 7) >> 3) *
1183 viacursor.image.height;
1184
1185 if (MAX_CURS == 32) {
1186 for (i = 0; i < (CURSOR_SIZE / 32); i++) {
1187 data_bak[i] = 0x0;
1188 data_bak[i + 1] = 0xFFFFFFFF;
1189 i += 1;
1190 }
1191 } else if (MAX_CURS == 64) {
1192 for (i = 0; i < (CURSOR_SIZE / 32); i++) {
1193 data_bak[i] = 0x0;
1194 data_bak[i + 1] = 0x0;
1195 data_bak[i + 2] = 0xFFFFFFFF;
1196 data_bak[i + 3] = 0xFFFFFFFF;
1197 i += 3;
1198 }
1199 }
1200
1201 switch (viacursor.rop) {
1202 case ROP_XOR:
1203 for (i = 0; i < size; i++)
1204 data[i] = viacursor.mask[i];
1205 break;
1206 case ROP_COPY:
1207
1208 for (i = 0; i < size; i++)
1209 data[i] = viacursor.mask[i];
1210 break;
1211 default:
1212 break;
1213 }
1214
1215 if (MAX_CURS == 32) {
1216 for (i = 0; i < size; i++) {
1217 data_bak[j] = (u32) data[i];
1218 data_bak[j + 1] = ~data_bak[j];
1219 j += 2;
1220 }
1221 } else if (MAX_CURS == 64) {
1222 for (i = 0; i < size; i++) {
1223 data_bak[j] = (u32) data[i];
1224 data_bak[j + 1] = 0x0;
1225 data_bak[j + 2] = ~data_bak[j];
1226 data_bak[j + 3] = ~data_bak[j + 1];
1227 j += 4;
1228 }
1229 }
1230
1231 memcpy(((struct viafb_par *)(info->par))->fbmem_virt +
1232 ((struct viafb_par *)(info->par))->cursor_start,
1233 data_bak, CURSOR_SIZE);
1234 }
1235
1236 if (viacursor.enable)
1237 viafb_show_hw_cursor(info, HW_Cursor_ON);
1238
1239 return 0;
1240}
1241
1242static int viafb_sync(struct fb_info *info)
1243{
1244 if (viafb_accel)
1245 viafb_wait_engine_idle();
1246 return 0;
1247}
1248
1249int viafb_get_mode_index(int hres, int vres, int flag)
1250{
1251 u32 i;
1252 DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
1253
1254 for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++)
1255 if (viafb_modentry[i].xres == hres &&
1256 viafb_modentry[i].yres == vres)
1257 break;
1258
1259 viafb_resMode = viafb_modentry[i].mode_index;
1260 if (flag)
1261 viafb_mode1 = viafb_modentry[i].mode_res;
1262 else
1263 viafb_mode = viafb_modentry[i].mode_res;
1264
1265 return viafb_resMode;
1266}
1267
1268static void check_available_device_to_enable(int device_id)
1269{
1270 int device_num = 0;
1271
1272 /* Initialize: */
1273 viafb_CRT_ON = STATE_OFF;
1274 viafb_DVI_ON = STATE_OFF;
1275 viafb_LCD_ON = STATE_OFF;
1276 viafb_LCD2_ON = STATE_OFF;
1277 viafb_DeviceStatus = None_Device;
1278
1279 if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1280 viafb_CRT_ON = STATE_ON;
1281 device_num++;
1282 viafb_DeviceStatus |= CRT_Device;
1283 }
1284
1285 if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1286 viafb_DVI_ON = STATE_ON;
1287 device_num++;
1288 viafb_DeviceStatus |= DVI_Device;
1289 }
1290
1291 if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1292 viafb_LCD_ON = STATE_ON;
1293 device_num++;
1294 viafb_DeviceStatus |= LCD_Device;
1295 }
1296
1297 if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
1298 viafb_LCD2_ON = STATE_ON;
1299 device_num++;
1300 viafb_DeviceStatus |= LCD2_Device;
1301 }
1302
1303 if (viafb_DeviceStatus == None_Device) {
1304 /* Use CRT as default active device: */
1305 viafb_CRT_ON = STATE_ON;
1306 viafb_DeviceStatus = CRT_Device;
1307 }
1308 DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus);
1309}
1310
1311static void viafb_set_device(struct device_t active_dev)
1312{
1313 /* Check available device to enable: */
1314 int device_id = None_Device;
1315 if (active_dev.crt)
1316 device_id |= CRT_Device;
1317 if (active_dev.dvi)
1318 device_id |= DVI_Device;
1319 if (active_dev.lcd)
1320 device_id |= LCD_Device;
1321
1322 check_available_device_to_enable(device_id);
1323
1324 /* Check property of LCD: */
1325 if (viafb_LCD_ON) {
1326 if (active_dev.lcd_dsp_cent) {
1327 viaparinfo->lvds_setting_info->display_method =
1328 viafb_lcd_dsp_method = LCD_CENTERING;
1329 } else {
1330 viaparinfo->lvds_setting_info->display_method =
1331 viafb_lcd_dsp_method = LCD_EXPANDSION;
1332 }
1333
1334 if (active_dev.lcd_mode == LCD_SPWG) {
1335 viaparinfo->lvds_setting_info->lcd_mode =
1336 viafb_lcd_mode = LCD_SPWG;
1337 } else {
1338 viaparinfo->lvds_setting_info->lcd_mode =
1339 viafb_lcd_mode = LCD_OPENLDI;
1340 }
1341
1342 if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) {
1343 viafb_lcd_panel_id = active_dev.lcd_panel_id;
1344 viafb_init_lcd_size();
1345 }
1346 }
1347
1348 /* Check property of mode: */
1349 if (!active_dev.xres1)
1350 viafb_second_xres = 640;
1351 else
1352 viafb_second_xres = active_dev.xres1;
1353 if (!active_dev.yres1)
1354 viafb_second_yres = 480;
1355 else
1356 viafb_second_yres = active_dev.yres1;
1357 if (active_dev.bpp != 0)
1358 viafb_bpp = active_dev.bpp;
1359 if (active_dev.bpp1 != 0)
1360 viafb_bpp1 = active_dev.bpp1;
1361 if (active_dev.refresh != 0)
1362 viafb_refresh = active_dev.refresh;
1363 if (active_dev.refresh1 != 0)
1364 viafb_refresh1 = active_dev.refresh1;
1365 if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON))
1366 viafb_SAMM_ON = active_dev.samm;
1367 viafb_primary_dev = active_dev.primary_dev;
1368
1369 viafb_set_start_addr();
1370 viafb_set_iga_path();
1371}
1372
1373static void viafb_set_video_device(u32 video_dev_info)
1374{
1375 viaparinfo->video_on_crt = STATE_OFF;
1376 viaparinfo->video_on_dvi = STATE_OFF;
1377 viaparinfo->video_on_lcd = STATE_OFF;
1378
1379 /* Check available device to enable: */
1380 if ((video_dev_info & CRT_Device) == CRT_Device)
1381 viaparinfo->video_on_crt = STATE_ON;
1382 else if ((video_dev_info & DVI_Device) == DVI_Device)
1383 viaparinfo->video_on_dvi = STATE_ON;
1384 else if ((video_dev_info & LCD_Device) == LCD_Device)
1385 viaparinfo->video_on_lcd = STATE_ON;
1386}
1387
1388static void viafb_get_video_device(u32 *video_dev_info)
1389{
1390 *video_dev_info = None_Device;
1391 if (viaparinfo->video_on_crt == STATE_ON)
1392 *video_dev_info |= CRT_Device;
1393 else if (viaparinfo->video_on_dvi == STATE_ON)
1394 *video_dev_info |= DVI_Device;
1395 else if (viaparinfo->video_on_lcd == STATE_ON)
1396 *video_dev_info |= LCD_Device;
1397}
1398
1399static int get_primary_device(void)
1400{
1401 int primary_device = 0;
1402 /* Rule: device on iga1 path are the primary device. */
1403 if (viafb_SAMM_ON) {
1404 if (viafb_CRT_ON) {
1405 if (viaparinfo->crt_setting_info->iga_path == IGA1) {
1406 DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n",
1407 viaparinfo->
1408 crt_setting_info->iga_path);
1409 primary_device = CRT_Device;
1410 }
1411 }
1412 if (viafb_DVI_ON) {
1413 if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
1414 DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
1415 viaparinfo->
1416 tmds_setting_info->iga_path);
1417 primary_device = DVI_Device;
1418 }
1419 }
1420 if (viafb_LCD_ON) {
1421 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1422 DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
1423 viaparinfo->
1424 lvds_setting_info->iga_path);
1425 primary_device = LCD_Device;
1426 }
1427 }
1428 if (viafb_LCD2_ON) {
1429 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
1430 DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
1431 viaparinfo->
1432 lvds_setting_info2->iga_path);
1433 primary_device = LCD2_Device;
1434 }
1435 }
1436 }
1437 return primary_device;
1438}
1439
1440static u8 is_duoview(void)
1441{
1442 if (0 == viafb_SAMM_ON) {
1443 if (viafb_LCD_ON + viafb_LCD2_ON +
1444 viafb_DVI_ON + viafb_CRT_ON == 2)
1445 return true;
1446 return false;
1447 } else {
1448 return false;
1449 }
1450}
1451
1452static void apply_second_mode_setting(struct fb_var_screeninfo
1453 *sec_var)
1454{
1455 u32 htotal, vtotal, long_refresh;
1456
1457 htotal = sec_var->xres + sec_var->left_margin +
1458 sec_var->right_margin + sec_var->hsync_len;
1459 vtotal = sec_var->yres + sec_var->upper_margin +
1460 sec_var->lower_margin + sec_var->vsync_len;
1461 if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) {
1462 /*Is 32 bytes alignment? */
1463 /*32 pixel alignment */
1464 sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31;
1465 }
1466
1467 htotal = sec_var->xres + sec_var->left_margin +
1468 sec_var->right_margin + sec_var->hsync_len;
1469 vtotal = sec_var->yres + sec_var->upper_margin +
1470 sec_var->lower_margin + sec_var->vsync_len;
1471 long_refresh = 1000000000UL / sec_var->pixclock * 1000;
1472 long_refresh /= (htotal * vtotal);
1473
1474 viafb_second_xres = sec_var->xres;
1475 viafb_second_yres = sec_var->yres;
1476 viafb_second_virtual_xres = sec_var->xres_virtual;
1477 viafb_second_virtual_yres = sec_var->yres_virtual;
1478 viafb_bpp1 = sec_var->bits_per_pixel;
1479 viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres,
1480 long_refresh);
1481}
1482
1483static int apply_device_setting(struct viafb_ioctl_setting setting_info,
1484 struct fb_info *info)
1485{
1486 int need_set_mode = 0;
1487 DEBUG_MSG(KERN_INFO "apply_device_setting\n");
1488
1489 if (setting_info.device_flag) {
1490 need_set_mode = 1;
1491 check_available_device_to_enable(setting_info.device_status);
1492 }
1493
1494 /* Unlock LCD's operation according to LCD flag
1495 and check if the setting value is valid. */
1496 /* If the value is valid, apply the new setting value to the device. */
1497 if (viafb_LCD_ON) {
1498 if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) {
1499 need_set_mode = 1;
1500 if (setting_info.lcd_attributes.display_center) {
1501 /* Centering */
1502 viaparinfo->lvds_setting_info->display_method =
1503 LCD_CENTERING;
1504 viafb_lcd_dsp_method = LCD_CENTERING;
1505 viaparinfo->lvds_setting_info2->display_method =
1506 viafb_lcd_dsp_method = LCD_CENTERING;
1507 } else {
1508 /* expandsion */
1509 viaparinfo->lvds_setting_info->display_method =
1510 LCD_EXPANDSION;
1511 viafb_lcd_dsp_method = LCD_EXPANDSION;
1512 viaparinfo->lvds_setting_info2->display_method =
1513 LCD_EXPANDSION;
1514 viafb_lcd_dsp_method = LCD_EXPANDSION;
1515 }
1516 }
1517
1518 if (setting_info.lcd_operation_flag & OP_LCD_MODE) {
1519 need_set_mode = 1;
1520 if (setting_info.lcd_attributes.lcd_mode ==
1521 LCD_SPWG) {
1522 viaparinfo->lvds_setting_info->lcd_mode =
1523 viafb_lcd_mode = LCD_SPWG;
1524 } else {
1525 viaparinfo->lvds_setting_info->lcd_mode =
1526 viafb_lcd_mode = LCD_OPENLDI;
1527 }
1528 viaparinfo->lvds_setting_info2->lcd_mode =
1529 viaparinfo->lvds_setting_info->lcd_mode;
1530 }
1531
1532 if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) {
1533 need_set_mode = 1;
1534 if (setting_info.lcd_attributes.panel_id <=
1535 LCD_PANEL_ID_MAXIMUM) {
1536 viafb_lcd_panel_id =
1537 setting_info.lcd_attributes.panel_id;
1538 viafb_init_lcd_size();
1539 }
1540 }
1541 }
1542
1543 if (0 != (setting_info.samm_status & OP_SAMM)) {
1544 setting_info.samm_status =
1545 setting_info.samm_status & (~OP_SAMM);
1546 if (setting_info.samm_status == 0
1547 || setting_info.samm_status == 1) {
1548 viafb_SAMM_ON = setting_info.samm_status;
1549
1550 if (viafb_SAMM_ON)
1551 viafb_primary_dev = setting_info.primary_device;
1552
1553 viafb_set_start_addr();
1554 viafb_set_iga_path();
1555 }
1556 need_set_mode = 1;
1557 }
1558
1559 viaparinfo->duoview = is_duoview();
1560
1561 if (!need_set_mode) {
1562 ;
1563 } else {
1564 viafb_set_iga_path();
1565 viafb_set_par(info);
1566 }
1567 return true;
1568}
1569
1570static void retrieve_device_setting(struct viafb_ioctl_setting
1571 *setting_info)
1572{
1573
1574 /* get device status */
1575 if (viafb_CRT_ON == 1)
1576 setting_info->device_status = CRT_Device;
1577 if (viafb_DVI_ON == 1)
1578 setting_info->device_status |= DVI_Device;
1579 if (viafb_LCD_ON == 1)
1580 setting_info->device_status |= LCD_Device;
1581 if (viafb_LCD2_ON == 1)
1582 setting_info->device_status |= LCD2_Device;
1583 if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) {
1584 setting_info->video_device_status =
1585 viaparinfo->crt_setting_info->iga_path;
1586 } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) {
1587 setting_info->video_device_status =
1588 viaparinfo->tmds_setting_info->iga_path;
1589 } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) {
1590 setting_info->video_device_status =
1591 viaparinfo->lvds_setting_info->iga_path;
1592 } else {
1593 setting_info->video_device_status = 0;
1594 }
1595
1596 setting_info->samm_status = viafb_SAMM_ON;
1597 setting_info->primary_device = get_primary_device();
1598
1599 setting_info->first_dev_bpp = viafb_bpp;
1600 setting_info->second_dev_bpp = viafb_bpp1;
1601
1602 setting_info->first_dev_refresh = viafb_refresh;
1603 setting_info->second_dev_refresh = viafb_refresh1;
1604
1605 setting_info->first_dev_hor_res = viafb_hotplug_Xres;
1606 setting_info->first_dev_ver_res = viafb_hotplug_Yres;
1607 setting_info->second_dev_hor_res = viafb_second_xres;
1608 setting_info->second_dev_ver_res = viafb_second_yres;
1609
1610 /* Get lcd attributes */
1611 setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
1612 setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
1613 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
1614}
1615
1616static void parse_active_dev(void)
1617{
1618 viafb_CRT_ON = STATE_OFF;
1619 viafb_DVI_ON = STATE_OFF;
1620 viafb_LCD_ON = STATE_OFF;
1621 viafb_LCD2_ON = STATE_OFF;
1622 /* 1. Modify the active status of devices. */
1623 /* 2. Keep the order of devices, so we can set corresponding
1624 IGA path to devices in SAMM case. */
1625 /* Note: The previous of active_dev is primary device,
1626 and the following is secondary device. */
1627 if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) {
1628 /* CRT+DVI */
1629 viafb_CRT_ON = STATE_ON;
1630 viafb_DVI_ON = STATE_ON;
1631 viafb_primary_dev = CRT_Device;
1632 } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) {
1633 /* DVI+CRT */
1634 viafb_CRT_ON = STATE_ON;
1635 viafb_DVI_ON = STATE_ON;
1636 viafb_primary_dev = DVI_Device;
1637 } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) {
1638 /* CRT+LCD */
1639 viafb_CRT_ON = STATE_ON;
1640 viafb_LCD_ON = STATE_ON;
1641 viafb_primary_dev = CRT_Device;
1642 } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) {
1643 /* LCD+CRT */
1644 viafb_CRT_ON = STATE_ON;
1645 viafb_LCD_ON = STATE_ON;
1646 viafb_primary_dev = LCD_Device;
1647 } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) {
1648 /* DVI+LCD */
1649 viafb_DVI_ON = STATE_ON;
1650 viafb_LCD_ON = STATE_ON;
1651 viafb_primary_dev = DVI_Device;
1652 } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) {
1653 /* LCD+DVI */
1654 viafb_DVI_ON = STATE_ON;
1655 viafb_LCD_ON = STATE_ON;
1656 viafb_primary_dev = LCD_Device;
1657 } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) {
1658 viafb_LCD_ON = STATE_ON;
1659 viafb_LCD2_ON = STATE_ON;
1660 viafb_primary_dev = LCD_Device;
1661 } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) {
1662 viafb_LCD_ON = STATE_ON;
1663 viafb_LCD2_ON = STATE_ON;
1664 viafb_primary_dev = LCD2_Device;
1665 } else if (!strncmp(viafb_active_dev, "CRT", 3)) {
1666 /* CRT only */
1667 viafb_CRT_ON = STATE_ON;
1668 viafb_SAMM_ON = STATE_OFF;
1669 } else if (!strncmp(viafb_active_dev, "DVI", 3)) {
1670 /* DVI only */
1671 viafb_DVI_ON = STATE_ON;
1672 viafb_SAMM_ON = STATE_OFF;
1673 } else if (!strncmp(viafb_active_dev, "LCD", 3)) {
1674 /* LCD only */
1675 viafb_LCD_ON = STATE_ON;
1676 viafb_SAMM_ON = STATE_OFF;
1677 } else {
1678 viafb_CRT_ON = STATE_ON;
1679 viafb_SAMM_ON = STATE_OFF;
1680 }
1681 viaparinfo->duoview = is_duoview();
1682}
1683
1684static void parse_video_dev(void)
1685{
1686 viaparinfo->video_on_crt = STATE_OFF;
1687 viaparinfo->video_on_dvi = STATE_OFF;
1688 viaparinfo->video_on_lcd = STATE_OFF;
1689
1690 if (!strncmp(viafb_video_dev, "CRT", 3)) {
1691 /* Video on CRT */
1692 viaparinfo->video_on_crt = STATE_ON;
1693 } else if (!strncmp(viafb_video_dev, "DVI", 3)) {
1694 /* Video on DVI */
1695 viaparinfo->video_on_dvi = STATE_ON;
1696 } else if (!strncmp(viafb_video_dev, "LCD", 3)) {
1697 /* Video on LCD */
1698 viaparinfo->video_on_lcd = STATE_ON;
1699 }
1700}
1701
1702static int parse_port(char *opt_str, int *output_interface)
1703{
1704 if (!strncmp(opt_str, "DVP0", 4))
1705 *output_interface = INTERFACE_DVP0;
1706 else if (!strncmp(opt_str, "DVP1", 4))
1707 *output_interface = INTERFACE_DVP1;
1708 else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
1709 *output_interface = INTERFACE_DFP;
1710 else if (!strncmp(opt_str, "DFP_HIGH", 8))
1711 *output_interface = INTERFACE_DFP_HIGH;
1712 else if (!strncmp(opt_str, "DFP_LOW", 7))
1713 *output_interface = INTERFACE_DFP_LOW;
1714 else
1715 *output_interface = INTERFACE_NONE;
1716 return 0;
1717}
1718
1719static void parse_lcd_port(void)
1720{
1721 parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
1722 output_interface);
1723 /*Initialize to avoid unexpected behavior */
1724 viaparinfo->chip_info->lvds_chip_info2.output_interface =
1725 INTERFACE_NONE;
1726
1727 DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
1728 viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
1729 output_interface);
1730}
1731
1732static void parse_dvi_port(void)
1733{
1734 parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
1735 output_interface);
1736
1737 DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
1738 viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
1739 output_interface);
1740}
1741
1742/*
1743 * The proc filesystem read/write function, a simple proc implement to
1744 * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
1745 * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2],
1746 * CR9B, SR65, CR97, CR99
1747 */
1748static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset,
1749int count, int *eof, void *data)
1750{
1751 int len = 0;
1752 u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
1753 dvp0_data_dri =
1754 (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
1755 (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
1756 dvp0_clk_dri =
1757 (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
1758 (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
1759 dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
1760 len +=
1761 sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
1762 *eof = 1; /*Inform kernel end of data */
1763 return len;
1764}
1765static int viafb_dvp0_proc_write(struct file *file,
1766 const char __user *buffer, unsigned long count, void *data)
1767{
1768 char buf[20], *value, *pbuf;
1769 u8 reg_val = 0;
1770 unsigned long length, i;
1771 if (count < 1)
1772 return -EINVAL;
1773 length = count > 20 ? 20 : count;
1774 if (copy_from_user(&buf[0], buffer, length))
1775 return -EFAULT;
1776 buf[length - 1] = '\0'; /*Ensure end string */
1777 pbuf = &buf[0];
1778 for (i = 0; i < 3; i++) {
1779 value = strsep(&pbuf, " ");
1780 if (value != NULL) {
1781 strict_strtoul(value, 0, (unsigned long *)&reg_val);
1782 DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
1783 reg_val);
1784 switch (i) {
1785 case 0:
1786 viafb_write_reg_mask(CR96, VIACR,
1787 reg_val, 0x0f);
1788 break;
1789 case 1:
1790 viafb_write_reg_mask(SR2A, VIASR,
1791 reg_val << 4, BIT5);
1792 viafb_write_reg_mask(SR1B, VIASR,
1793 reg_val << 1, BIT1);
1794 break;
1795 case 2:
1796 viafb_write_reg_mask(SR2A, VIASR,
1797 reg_val << 3, BIT4);
1798 viafb_write_reg_mask(SR1E, VIASR,
1799 reg_val << 2, BIT2);
1800 break;
1801 default:
1802 break;
1803 }
1804 } else {
1805 break;
1806 }
1807 }
1808 return count;
1809}
1810static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset,
1811 int count, int *eof, void *data)
1812{
1813 int len = 0;
1814 u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
1815 dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
1816 dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
1817 dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
1818 len +=
1819 sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
1820 *eof = 1; /*Inform kernel end of data */
1821 return len;
1822}
1823static int viafb_dvp1_proc_write(struct file *file,
1824 const char __user *buffer, unsigned long count, void *data)
1825{
1826 char buf[20], *value, *pbuf;
1827 u8 reg_val = 0;
1828 unsigned long length, i;
1829 if (count < 1)
1830 return -EINVAL;
1831 length = count > 20 ? 20 : count;
1832 if (copy_from_user(&buf[0], buffer, length))
1833 return -EFAULT;
1834 buf[length - 1] = '\0'; /*Ensure end string */
1835 pbuf = &buf[0];
1836 for (i = 0; i < 3; i++) {
1837 value = strsep(&pbuf, " ");
1838 if (value != NULL) {
1839 strict_strtoul(value, 0, (unsigned long *)&reg_val);
1840 switch (i) {
1841 case 0:
1842 viafb_write_reg_mask(CR9B, VIACR,
1843 reg_val, 0x0f);
1844 break;
1845 case 1:
1846 viafb_write_reg_mask(SR65, VIASR,
1847 reg_val << 2, 0x0c);
1848 break;
1849 case 2:
1850 viafb_write_reg_mask(SR65, VIASR,
1851 reg_val, 0x03);
1852 break;
1853 default:
1854 break;
1855 }
1856 } else {
1857 break;
1858 }
1859 }
1860 return count;
1861}
1862
1863static int viafb_dfph_proc_read(char *buf, char **start, off_t offset,
1864 int count, int *eof, void *data)
1865{
1866 int len = 0;
1867 u8 dfp_high = 0;
1868 dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
1869 len += sprintf(buf + len, "%x\n", dfp_high);
1870 *eof = 1; /*Inform kernel end of data */
1871 return len;
1872}
1873static int viafb_dfph_proc_write(struct file *file,
1874 const char __user *buffer, unsigned long count, void *data)
1875{
1876 char buf[20];
1877 u8 reg_val = 0;
1878 unsigned long length;
1879 if (count < 1)
1880 return -EINVAL;
1881 length = count > 20 ? 20 : count;
1882 if (copy_from_user(&buf[0], buffer, length))
1883 return -EFAULT;
1884 buf[length - 1] = '\0'; /*Ensure end string */
1885 strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
1886 viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
1887 return count;
1888}
1889static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset,
1890 int count, int *eof, void *data)
1891{
1892 int len = 0;
1893 u8 dfp_low = 0;
1894 dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
1895 len += sprintf(buf + len, "%x\n", dfp_low);
1896 *eof = 1; /*Inform kernel end of data */
1897 return len;
1898}
1899static int viafb_dfpl_proc_write(struct file *file,
1900 const char __user *buffer, unsigned long count, void *data)
1901{
1902 char buf[20];
1903 u8 reg_val = 0;
1904 unsigned long length;
1905 if (count < 1)
1906 return -EINVAL;
1907 length = count > 20 ? 20 : count;
1908 if (copy_from_user(&buf[0], buffer, length))
1909 return -EFAULT;
1910 buf[length - 1] = '\0'; /*Ensure end string */
1911 strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
1912 viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
1913 return count;
1914}
1915static int viafb_vt1636_proc_read(char *buf, char **start,
1916 off_t offset, int count, int *eof, void *data)
1917{
1918 int len = 0;
1919 u8 vt1636_08 = 0, vt1636_09 = 0;
1920 switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1921 case VT1636_LVDS:
1922 vt1636_08 =
1923 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1924 &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
1925 vt1636_09 =
1926 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1927 &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
1928 len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09);
1929 break;
1930 default:
1931 break;
1932 }
1933 switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1934 case VT1636_LVDS:
1935 vt1636_08 =
1936 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1937 &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
1938 vt1636_09 =
1939 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1940 &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
1941 len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09);
1942 break;
1943 default:
1944 break;
1945 }
1946 *eof = 1; /*Inform kernel end of data */
1947 return len;
1948}
1949static int viafb_vt1636_proc_write(struct file *file,
1950 const char __user *buffer, unsigned long count, void *data)
1951{
1952 char buf[30], *value, *pbuf;
1953 struct IODATA reg_val;
1954 unsigned long length, i;
1955 if (count < 1)
1956 return -EINVAL;
1957 length = count > 30 ? 30 : count;
1958 if (copy_from_user(&buf[0], buffer, length))
1959 return -EFAULT;
1960 buf[length - 1] = '\0'; /*Ensure end string */
1961 pbuf = &buf[0];
1962 switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1963 case VT1636_LVDS:
1964 for (i = 0; i < 2; i++) {
1965 value = strsep(&pbuf, " ");
1966 if (value != NULL) {
1967 strict_strtoul(value, 0,
1968 (unsigned long *)&reg_val.Data);
1969 switch (i) {
1970 case 0:
1971 reg_val.Index = 0x08;
1972 reg_val.Mask = 0x0f;
1973 viafb_gpio_i2c_write_mask_lvds
1974 (viaparinfo->lvds_setting_info,
1975 &viaparinfo->
1976 chip_info->lvds_chip_info,
1977 reg_val);
1978 break;
1979 case 1:
1980 reg_val.Index = 0x09;
1981 reg_val.Mask = 0x1f;
1982 viafb_gpio_i2c_write_mask_lvds
1983 (viaparinfo->lvds_setting_info,
1984 &viaparinfo->
1985 chip_info->lvds_chip_info,
1986 reg_val);
1987 break;
1988 default:
1989 break;
1990 }
1991 } else {
1992 break;
1993 }
1994 }
1995 break;
1996 default:
1997 break;
1998 }
1999 switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2000 case VT1636_LVDS:
2001 for (i = 0; i < 2; i++) {
2002 value = strsep(&pbuf, " ");
2003 if (value != NULL) {
2004 strict_strtoul(value, 0,
2005 (unsigned long *)&reg_val.Data);
2006 switch (i) {
2007 case 0:
2008 reg_val.Index = 0x08;
2009 reg_val.Mask = 0x0f;
2010 viafb_gpio_i2c_write_mask_lvds
2011 (viaparinfo->lvds_setting_info2,
2012 &viaparinfo->
2013 chip_info->lvds_chip_info2,
2014 reg_val);
2015 break;
2016 case 1:
2017 reg_val.Index = 0x09;
2018 reg_val.Mask = 0x1f;
2019 viafb_gpio_i2c_write_mask_lvds
2020 (viaparinfo->lvds_setting_info2,
2021 &viaparinfo->
2022 chip_info->lvds_chip_info2,
2023 reg_val);
2024 break;
2025 default:
2026 break;
2027 }
2028 } else {
2029 break;
2030 }
2031 }
2032 break;
2033 default:
2034 break;
2035 }
2036 return count;
2037}
2038
2039static void viafb_init_proc(struct proc_dir_entry *viafb_entry)
2040{
2041 struct proc_dir_entry *entry;
2042 viafb_entry = proc_mkdir("viafb", NULL);
2043 if (viafb_entry) {
2044 entry = create_proc_entry("dvp0", 0, viafb_entry);
2045 if (entry) {
2046 entry->owner = THIS_MODULE;
2047 entry->read_proc = viafb_dvp0_proc_read;
2048 entry->write_proc = viafb_dvp0_proc_write;
2049 }
2050 entry = create_proc_entry("dvp1", 0, viafb_entry);
2051 if (entry) {
2052 entry->owner = THIS_MODULE;
2053 entry->read_proc = viafb_dvp1_proc_read;
2054 entry->write_proc = viafb_dvp1_proc_write;
2055 }
2056 entry = create_proc_entry("dfph", 0, viafb_entry);
2057 if (entry) {
2058 entry->owner = THIS_MODULE;
2059 entry->read_proc = viafb_dfph_proc_read;
2060 entry->write_proc = viafb_dfph_proc_write;
2061 }
2062 entry = create_proc_entry("dfpl", 0, viafb_entry);
2063 if (entry) {
2064 entry->owner = THIS_MODULE;
2065 entry->read_proc = viafb_dfpl_proc_read;
2066 entry->write_proc = viafb_dfpl_proc_write;
2067 }
2068 if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
2069 lvds_chip_name || VT1636_LVDS ==
2070 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2071 entry = create_proc_entry("vt1636", 0, viafb_entry);
2072 if (entry) {
2073 entry->owner = THIS_MODULE;
2074 entry->read_proc = viafb_vt1636_proc_read;
2075 entry->write_proc = viafb_vt1636_proc_write;
2076 }
2077 }
2078
2079 }
2080}
2081static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
2082{
2083 /* no problem if it was not registered */
2084 remove_proc_entry("dvp0", viafb_entry);/* parent dir */
2085 remove_proc_entry("dvp1", viafb_entry);
2086 remove_proc_entry("dfph", viafb_entry);
2087 remove_proc_entry("dfpl", viafb_entry);
2088 remove_proc_entry("vt1636", viafb_entry);
2089 remove_proc_entry("vt1625", viafb_entry);
2090}
2091
2092static int __devinit via_pci_probe(void)
2093{
2094 unsigned int default_xres, default_yres;
2095 char *tmpc, *tmpm;
2096 char *tmpc_sec, *tmpm_sec;
2097 int vmode_index;
2098 u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length;
2099
2100 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
2101
2102 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
2103 tmds_length = ALIGN(sizeof(struct tmds_setting_information),
2104 BITS_PER_LONG/8);
2105 lvds_length = ALIGN(sizeof(struct lvds_setting_information),
2106 BITS_PER_LONG/8);
2107 crt_length = ALIGN(sizeof(struct lvds_setting_information),
2108 BITS_PER_LONG/8);
2109 chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8);
2110
2111 /* Allocate fb_info and ***_par here, also including some other needed
2112 * variables
2113 */
2114 viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length +
2115 tmds_length + crt_length + chip_length, NULL);
2116 if (!viafbinfo) {
2117 printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
2118 return -ENODEV;
2119 }
2120
2121 viaparinfo = (struct viafb_par *)viafbinfo->par;
2122 viaparinfo->tmds_setting_info = (struct tmds_setting_information *)
2123 ((unsigned long)viaparinfo + viafb_par_length);
2124 viaparinfo->lvds_setting_info = (struct lvds_setting_information *)
2125 ((unsigned long)viaparinfo->tmds_setting_info + tmds_length);
2126 viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *)
2127 ((unsigned long)viaparinfo->lvds_setting_info + lvds_length);
2128 viaparinfo->crt_setting_info = (struct crt_setting_information *)
2129 ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length);
2130 viaparinfo->chip_info = (struct chip_information *)
2131 ((unsigned long)viaparinfo->crt_setting_info + crt_length);
2132
2133 if (viafb_dual_fb)
2134 viafb_SAMM_ON = 1;
2135 parse_active_dev();
2136 parse_video_dev();
2137 parse_lcd_port();
2138 parse_dvi_port();
2139
2140 /* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */
2141 if (!viafb_SAMM_ON)
2142 viafb_dual_fb = 0;
2143
2144 /* Set up I2C bus stuff */
2145 viafb_create_i2c_bus(viaparinfo);
2146
2147 viafb_init_chip_info();
2148 viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize);
2149 viaparinfo->fbmem_free = viaparinfo->memsize;
2150 viaparinfo->fbmem_used = 0;
2151 viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem,
2152 viaparinfo->memsize);
2153 viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt;
2154
2155 if (!viaparinfo->fbmem_virt) {
2156 printk(KERN_INFO "ioremap failed\n");
2157 return -1;
2158 }
2159
2160 viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len);
2161 viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base,
2162 viaparinfo->mmio_len);
2163
2164 viafbinfo->node = 0;
2165 viafbinfo->fbops = &viafb_ops;
2166 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2167
2168 viafbinfo->pseudo_palette = pseudo_pal;
2169 if (viafb_accel) {
2170 viafb_init_accel();
2171 viafb_init_2d_engine();
2172 viafb_hw_cursor_init();
2173 }
2174
2175 if (viafb_second_size && (viafb_second_size < 8)) {
2176 viafb_second_offset = viaparinfo->fbmem_free -
2177 viafb_second_size * 1024 * 1024;
2178 } else {
2179 viafb_second_size = 8;
2180 viafb_second_offset = viaparinfo->fbmem_free -
2181 viafb_second_size * 1024 * 1024;
2182 }
2183
2184 viafb_FB_MM = viaparinfo->fbmem_virt;
2185 tmpm = viafb_mode;
2186 tmpc = strsep(&tmpm, "x");
2187 strict_strtoul(tmpc, 0, (unsigned long *)&default_xres);
2188 strict_strtoul(tmpm, 0, (unsigned long *)&default_yres);
2189
2190 vmode_index = viafb_get_mode_index(default_xres, default_yres, 0);
2191 DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
2192
2193 if (viafb_SAMM_ON == 1) {
2194 if (strcmp(viafb_mode, viafb_mode1)) {
2195 tmpm_sec = viafb_mode1;
2196 tmpc_sec = strsep(&tmpm_sec, "x");
2197 strict_strtoul(tmpc_sec, 0,
2198 (unsigned long *)&viafb_second_xres);
2199 strict_strtoul(tmpm_sec, 0,
2200 (unsigned long *)&viafb_second_yres);
2201 } else {
2202 viafb_second_xres = default_xres;
2203 viafb_second_yres = default_yres;
2204 }
2205 if (0 == viafb_second_virtual_xres) {
2206 switch (viafb_second_xres) {
2207 case 1400:
2208 viafb_second_virtual_xres = 1408;
2209 break;
2210 default:
2211 viafb_second_virtual_xres = viafb_second_xres;
2212 break;
2213 }
2214 }
2215 if (0 == viafb_second_virtual_yres)
2216 viafb_second_virtual_yres = viafb_second_yres;
2217 }
2218
2219 switch (viafb_bpp) {
2220 case 0 ... 8:
2221 viafb_bpp = 8;
2222 break;
2223 case 9 ... 16:
2224 viafb_bpp = 16;
2225 break;
2226 case 17 ... 32:
2227 viafb_bpp = 32;
2228 break;
2229 default:
2230 viafb_bpp = 8;
2231 }
2232 default_var.xres = default_xres;
2233 default_var.yres = default_yres;
2234 switch (default_xres) {
2235 case 1400:
2236 default_var.xres_virtual = 1408;
2237 break;
2238 default:
2239 default_var.xres_virtual = default_xres;
2240 break;
2241 }
2242 default_var.yres_virtual = default_yres;
2243 default_var.bits_per_pixel = viafb_bpp;
2244 if (default_var.bits_per_pixel == 15)
2245 default_var.bits_per_pixel = 16;
2246 default_var.pixclock =
2247 viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
2248 default_var.left_margin = (default_xres >> 3) & 0xf8;
2249 default_var.right_margin = 32;
2250 default_var.upper_margin = 16;
2251 default_var.lower_margin = 4;
2252 default_var.hsync_len = default_var.left_margin;
2253 default_var.vsync_len = 4;
2254 default_var.accel_flags = 0;
2255
2256 if (viafb_accel) {
2257 viafbinfo->flags |=
2258 (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
2259 FBINFO_HWACCEL_IMAGEBLIT);
2260 default_var.accel_flags |= FB_ACCELF_TEXT;
2261 } else
2262 viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
2263
2264 if (viafb_dual_fb) {
2265 viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL);
2266 if (!viafbinfo1) {
2267 printk(KERN_ERR
2268 "allocate the second framebuffer struct error\n");
2269 framebuffer_release(viafbinfo);
2270 return -ENOMEM;
2271 }
2272 viaparinfo1 = viafbinfo1->par;
2273 memcpy(viaparinfo1, viaparinfo, viafb_par_length);
2274 viaparinfo1->memsize = viaparinfo->memsize -
2275 viafb_second_offset;
2276 viaparinfo->memsize = viafb_second_offset;
2277 viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt +
2278 viafb_second_offset;
2279 viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
2280
2281 viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
2282 viaparinfo1->fbmem_free = viaparinfo1->memsize -
2283 viaparinfo1->fbmem_used;
2284 viaparinfo->fbmem_free = viaparinfo->memsize;
2285 viaparinfo->fbmem_used = 0;
2286 if (viafb_accel) {
2287 viaparinfo1->cursor_start =
2288 viaparinfo->cursor_start - viafb_second_offset;
2289 viaparinfo1->VQ_start = viaparinfo->VQ_start -
2290 viafb_second_offset;
2291 viaparinfo1->VQ_end = viaparinfo->VQ_end -
2292 viafb_second_offset;
2293 }
2294
2295 memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
2296 viafbinfo1->screen_base = viafbinfo->screen_base +
2297 viafb_second_offset;
2298 viafbinfo1->fix.smem_start = viaparinfo1->fbmem;
2299 viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free;
2300
2301 default_var.xres = viafb_second_xres;
2302 default_var.yres = viafb_second_yres;
2303 default_var.xres_virtual = viafb_second_virtual_xres;
2304 default_var.yres_virtual = viafb_second_virtual_yres;
2305 if (viafb_bpp1 != viafb_bpp)
2306 viafb_bpp1 = viafb_bpp;
2307 default_var.bits_per_pixel = viafb_bpp1;
2308 default_var.pixclock =
2309 viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
2310 viafb_refresh);
2311 default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
2312 default_var.right_margin = 32;
2313 default_var.upper_margin = 16;
2314 default_var.lower_margin = 4;
2315 default_var.hsync_len = default_var.left_margin;
2316 default_var.vsync_len = 4;
2317
2318 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
2319 viafb_check_var(&default_var, viafbinfo1);
2320 viafbinfo1->var = default_var;
2321 viafb_update_viafb_par(viafbinfo);
2322 viafb_update_fix(&viafbinfo1->fix, viafbinfo1);
2323 }
2324
2325 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
2326 viafb_check_var(&default_var, viafbinfo);
2327 viafbinfo->var = default_var;
2328 viafb_update_viafb_par(viafbinfo);
2329 viafb_update_fix(&viafbinfo->fix, viafbinfo);
2330 default_var.activate = FB_ACTIVATE_NOW;
2331 fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
2332
2333 if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
2334 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
2335 if (register_framebuffer(viafbinfo1) < 0)
2336 return -EINVAL;
2337 }
2338 if (register_framebuffer(viafbinfo) < 0)
2339 return -EINVAL;
2340
2341 if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
2342 || (viaparinfo->chip_info->gfx_chip_name !=
2343 UNICHROME_CLE266))) {
2344 if (register_framebuffer(viafbinfo1) < 0)
2345 return -EINVAL;
2346 }
2347 DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
2348 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
2349 default_var.yres, default_var.bits_per_pixel);
2350
2351 viafb_init_proc(viaparinfo->proc_entry);
2352 viafb_init_dac(IGA2);
2353 return 0;
2354}
2355
2356static void __devexit via_pci_remove(void)
2357{
2358 DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
2359 fb_dealloc_cmap(&viafbinfo->cmap);
2360 unregister_framebuffer(viafbinfo);
2361 if (viafb_dual_fb)
2362 unregister_framebuffer(viafbinfo1);
2363 iounmap((void *)viaparinfo->fbmem_virt);
2364 iounmap(viaparinfo->io_virt);
2365
2366 viafb_delete_i2c_buss(viaparinfo);
2367
2368 framebuffer_release(viafbinfo);
2369 if (viafb_dual_fb)
2370 framebuffer_release(viafbinfo1);
2371
2372 viafb_remove_proc(viaparinfo->proc_entry);
2373}
2374
2375#ifndef MODULE
2376static int __init viafb_setup(char *options)
2377{
2378 char *this_opt;
2379 DEBUG_MSG(KERN_INFO "viafb_setup!\n");
2380
2381 if (!options || !*options)
2382 return 0;
2383
2384 while ((this_opt = strsep(&options, ",")) != NULL) {
2385 if (!*this_opt)
2386 continue;
2387
2388 if (!strncmp(this_opt, "viafb_mode1=", 12))
2389 viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
2390 else if (!strncmp(this_opt, "viafb_mode=", 11))
2391 viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
2392 else if (!strncmp(this_opt, "viafb_bpp1=", 11))
2393 strict_strtoul(this_opt + 11, 0,
2394 (unsigned long *)&viafb_bpp1);
2395 else if (!strncmp(this_opt, "viafb_bpp=", 10))
2396 strict_strtoul(this_opt + 10, 0,
2397 (unsigned long *)&viafb_bpp);
2398 else if (!strncmp(this_opt, "viafb_refresh1=", 15))
2399 strict_strtoul(this_opt + 15, 0,
2400 (unsigned long *)&viafb_refresh1);
2401 else if (!strncmp(this_opt, "viafb_refresh=", 14))
2402 strict_strtoul(this_opt + 14, 0,
2403 (unsigned long *)&viafb_refresh);
2404 else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
2405 strict_strtoul(this_opt + 21, 0,
2406 (unsigned long *)&viafb_lcd_dsp_method);
2407 else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
2408 strict_strtoul(this_opt + 19, 0,
2409 (unsigned long *)&viafb_lcd_panel_id);
2410 else if (!strncmp(this_opt, "viafb_accel=", 12))
2411 strict_strtoul(this_opt + 12, 0,
2412 (unsigned long *)&viafb_accel);
2413 else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
2414 strict_strtoul(this_opt + 14, 0,
2415 (unsigned long *)&viafb_SAMM_ON);
2416 else if (!strncmp(this_opt, "viafb_active_dev=", 17))
2417 viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
2418 else if (!strncmp(this_opt,
2419 "viafb_display_hardware_layout=", 30))
2420 strict_strtoul(this_opt + 30, 0,
2421 (unsigned long *)&viafb_display_hardware_layout);
2422 else if (!strncmp(this_opt, "viafb_second_size=", 18))
2423 strict_strtoul(this_opt + 18, 0,
2424 (unsigned long *)&viafb_second_size);
2425 else if (!strncmp(this_opt,
2426 "viafb_platform_epia_dvi=", 24))
2427 strict_strtoul(this_opt + 24, 0,
2428 (unsigned long *)&viafb_platform_epia_dvi);
2429 else if (!strncmp(this_opt,
2430 "viafb_device_lcd_dualedge=", 26))
2431 strict_strtoul(this_opt + 26, 0,
2432 (unsigned long *)&viafb_device_lcd_dualedge);
2433 else if (!strncmp(this_opt, "viafb_bus_width=", 16))
2434 strict_strtoul(this_opt + 16, 0,
2435 (unsigned long *)&viafb_bus_width);
2436 else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
2437 strict_strtoul(this_opt + 15, 0,
2438 (unsigned long *)&viafb_lcd_mode);
2439 else if (!strncmp(this_opt, "viafb_video_dev=", 16))
2440 viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL);
2441 else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
2442 viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
2443 else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
2444 viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
2445 }
2446 return 0;
2447}
2448#endif
2449
2450static int __init viafb_init(void)
2451{
2452#ifndef MODULE
2453 char *option = NULL;
2454 if (fb_get_options("viafb", &option))
2455 return -ENODEV;
2456 viafb_setup(option);
2457#endif
2458 printk(KERN_INFO
2459 "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
2460 VERSION_MAJOR, VERSION_MINOR);
2461 return via_pci_probe();
2462}
2463
2464static void __exit viafb_exit(void)
2465{
2466 DEBUG_MSG(KERN_INFO "viafb_exit!\n");
2467 via_pci_remove();
2468}
2469
2470static struct fb_ops viafb_ops = {
2471 .owner = THIS_MODULE,
2472 .fb_open = viafb_open,
2473 .fb_release = viafb_release,
2474 .fb_check_var = viafb_check_var,
2475 .fb_set_par = viafb_set_par,
2476 .fb_setcolreg = viafb_setcolreg,
2477 .fb_pan_display = viafb_pan_display,
2478 .fb_blank = viafb_blank,
2479 .fb_fillrect = viafb_fillrect,
2480 .fb_copyarea = viafb_copyarea,
2481 .fb_imageblit = viafb_imageblit,
2482 .fb_cursor = viafb_cursor,
2483 .fb_ioctl = viafb_ioctl,
2484 .fb_sync = viafb_sync,
2485 .fb_setcmap = viafb_setcmap,
2486};
2487
2488module_init(viafb_init);
2489module_exit(viafb_exit);
2490
2491#ifdef MODULE
2492module_param(viafb_memsize, int, 0);
2493
2494module_param(viafb_mode, charp, 0);
2495MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
2496
2497module_param(viafb_mode1, charp, 0);
2498MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
2499
2500module_param(viafb_bpp, int, 0);
2501MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
2502
2503module_param(viafb_bpp1, int, 0);
2504MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
2505
2506module_param(viafb_refresh, int, 0);
2507MODULE_PARM_DESC(viafb_refresh,
2508 "Set CRT viafb_refresh rate (default = 60)");
2509
2510module_param(viafb_refresh1, int, 0);
2511MODULE_PARM_DESC(viafb_refresh1,
2512 "Set CRT refresh rate (default = 60)");
2513
2514module_param(viafb_lcd_panel_id, int, 0);
2515MODULE_PARM_DESC(viafb_lcd_panel_id,
2516 "Set Flat Panel type(Default=1024x768)");
2517
2518module_param(viafb_lcd_dsp_method, int, 0);
2519MODULE_PARM_DESC(viafb_lcd_dsp_method,
2520 "Set Flat Panel display scaling method.(Default=Expandsion)");
2521
2522module_param(viafb_SAMM_ON, int, 0);
2523MODULE_PARM_DESC(viafb_SAMM_ON,
2524 "Turn on/off flag of SAMM(Default=OFF)");
2525
2526module_param(viafb_accel, int, 0);
2527MODULE_PARM_DESC(viafb_accel,
2528 "Set 2D Hardware Acceleration.(Default = OFF)");
2529
2530module_param(viafb_active_dev, charp, 0);
2531MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
2532
2533module_param(viafb_display_hardware_layout, int, 0);
2534MODULE_PARM_DESC(viafb_display_hardware_layout,
2535 "Display Hardware Layout (LCD Only, DVI Only...,etc)");
2536
2537module_param(viafb_second_size, int, 0);
2538MODULE_PARM_DESC(viafb_second_size,
2539 "Set secondary device memory size");
2540
2541module_param(viafb_dual_fb, int, 0);
2542MODULE_PARM_DESC(viafb_dual_fb,
2543 "Turn on/off flag of dual framebuffer devices.(Default = OFF)");
2544
2545module_param(viafb_platform_epia_dvi, int, 0);
2546MODULE_PARM_DESC(viafb_platform_epia_dvi,
2547 "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
2548
2549module_param(viafb_device_lcd_dualedge, int, 0);
2550MODULE_PARM_DESC(viafb_device_lcd_dualedge,
2551 "Turn on/off flag of dual edge panel.(Default = OFF)");
2552
2553module_param(viafb_bus_width, int, 0);
2554MODULE_PARM_DESC(viafb_bus_width,
2555 "Set bus width of panel.(Default = 12)");
2556
2557module_param(viafb_lcd_mode, int, 0);
2558MODULE_PARM_DESC(viafb_lcd_mode,
2559 "Set Flat Panel mode(Default=OPENLDI)");
2560
2561module_param(viafb_video_dev, charp, 0);
2562MODULE_PARM_DESC(viafb_video_dev, "Specify video devices.");
2563
2564module_param(viafb_lcd_port, charp, 0);
2565MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
2566
2567module_param(viafb_dvi_port, charp, 0);
2568MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
2569
2570MODULE_LICENSE("GPL");
2571#endif
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
new file mode 100644
index 000000000000..a4158e872878
--- /dev/null
+++ b/drivers/video/via/viafbdev.h
@@ -0,0 +1,112 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __VIAFBDEV_H__
23#define __VIAFBDEV_H__
24
25#include <linux/proc_fs.h>
26#include <linux/fb.h>
27
28#include "ioctl.h"
29#include "share.h"
30#include "chip.h"
31#include "hw.h"
32#include "via_i2c.h"
33
34#define VERSION_MAJOR 2
35#define VERSION_KERNEL 6 /* For kernel 2.6 */
36
37#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */
38#define VERSION_MINOR 4
39
40struct viafb_par {
41 int bpp;
42 int hres;
43 int vres;
44 int linelength;
45 u32 xoffset;
46 u32 yoffset;
47
48 void __iomem *fbmem_virt; /*framebuffer virtual memory address */
49 void __iomem *io_virt; /*iospace virtual memory address */
50 unsigned int fbmem; /*framebuffer physical memory address */
51 unsigned int memsize; /*size of fbmem */
52 unsigned int io; /*io space address */
53 unsigned long mmio_base; /*mmio base address */
54 unsigned long mmio_len; /*mmio base length */
55 u32 fbmem_free; /* Free FB memory */
56 u32 fbmem_used; /* Use FB memory size */
57 u32 cursor_start; /* Cursor Start Address */
58 u32 VQ_start; /* Virtual Queue Start Address */
59 u32 VQ_end; /* Virtual Queue End Address */
60 u32 iga_path;
61 struct proc_dir_entry *proc_entry; /*viafb proc entry */
62 u8 duoview; /*Is working in duoview mode? */
63
64 /* I2C stuff */
65 struct via_i2c_stuff i2c_stuff;
66
67 /* All the information will be needed to set engine */
68 struct tmds_setting_information *tmds_setting_info;
69 struct crt_setting_information *crt_setting_info;
70 struct lvds_setting_information *lvds_setting_info;
71 struct lvds_setting_information *lvds_setting_info2;
72 struct chip_information *chip_info;
73
74 /* some information related to video playing */
75 int video_on_crt;
76 int video_on_dvi;
77 int video_on_lcd;
78
79};
80struct viafb_modeinfo {
81 u32 xres;
82 u32 yres;
83 int mode_index;
84 char *mode_res;
85};
86extern unsigned int viafb_second_virtual_yres;
87extern unsigned int viafb_second_virtual_xres;
88extern unsigned int viafb_second_offset;
89extern int viafb_second_size;
90extern int viafb_SAMM_ON;
91extern int viafb_dual_fb;
92extern int viafb_LCD2_ON;
93extern int viafb_LCD_ON;
94extern int viafb_DVI_ON;
95extern int viafb_accel;
96extern int viafb_hotplug;
97extern int viafb_memsize;
98
99extern int strict_strtoul(const char *cp, unsigned int base,
100 unsigned long *res);
101
102void viafb_memory_pitch_patch(struct fb_info *info);
103void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
104 int mode_index);
105int viafb_get_mode_index(int hres, int vres, int flag);
106u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
107 *plvds_setting_info, struct lvds_chip_information
108 *plvds_chip_info, u8 index);
109void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
110 *plvds_setting_info, struct lvds_chip_information
111 *plvds_chip_info, struct IODATA io_data);
112#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
new file mode 100644
index 000000000000..6dcf583a837d
--- /dev/null
+++ b/drivers/video/via/viamode.c
@@ -0,0 +1,1086 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23struct res_map_refresh res_map_refresh_tbl[] = {
24/*hres, vres, vclock, vmode_refresh*/
25 {480, 640, RES_480X640_60HZ_PIXCLOCK, 60},
26 {640, 480, RES_640X480_60HZ_PIXCLOCK, 60},
27 {640, 480, RES_640X480_75HZ_PIXCLOCK, 75},
28 {640, 480, RES_640X480_85HZ_PIXCLOCK, 85},
29 {640, 480, RES_640X480_100HZ_PIXCLOCK, 100},
30 {640, 480, RES_640X480_120HZ_PIXCLOCK, 120},
31 {720, 480, RES_720X480_60HZ_PIXCLOCK, 60},
32 {720, 576, RES_720X576_60HZ_PIXCLOCK, 60},
33 {800, 480, RES_800X480_60HZ_PIXCLOCK, 60},
34 {800, 600, RES_800X600_60HZ_PIXCLOCK, 60},
35 {800, 600, RES_800X600_75HZ_PIXCLOCK, 75},
36 {800, 600, RES_800X600_85HZ_PIXCLOCK, 85},
37 {800, 600, RES_800X600_100HZ_PIXCLOCK, 100},
38 {800, 600, RES_800X600_120HZ_PIXCLOCK, 120},
39 {848, 480, RES_848X480_60HZ_PIXCLOCK, 60},
40 {856, 480, RES_856X480_60HZ_PIXCLOCK, 60},
41 {1024, 512, RES_1024X512_60HZ_PIXCLOCK, 60},
42 {1024, 600, RES_1024X600_60HZ_PIXCLOCK, 60},
43 {1024, 768, RES_1024X768_60HZ_PIXCLOCK, 60},
44 {1024, 768, RES_1024X768_75HZ_PIXCLOCK, 75},
45 {1024, 768, RES_1024X768_85HZ_PIXCLOCK, 85},
46 {1024, 768, RES_1024X768_100HZ_PIXCLOCK, 100},
47/* {1152,864, RES_1152X864_70HZ_PIXCLOCK, 70},*/
48 {1152, 864, RES_1152X864_75HZ_PIXCLOCK, 75},
49 {1280, 768, RES_1280X768_60HZ_PIXCLOCK, 60},
50 {1280, 800, RES_1280X800_60HZ_PIXCLOCK, 60},
51 {1280, 960, RES_1280X960_60HZ_PIXCLOCK, 60},
52 {1280, 1024, RES_1280X1024_60HZ_PIXCLOCK, 60},
53 {1280, 1024, RES_1280X1024_75HZ_PIXCLOCK, 75},
54 {1280, 1024, RES_1280X768_85HZ_PIXCLOCK, 85},
55 {1440, 1050, RES_1440X1050_60HZ_PIXCLOCK, 60},
56 {1600, 1200, RES_1600X1200_60HZ_PIXCLOCK, 60},
57 {1600, 1200, RES_1600X1200_75HZ_PIXCLOCK, 75},
58 {1280, 720, RES_1280X720_60HZ_PIXCLOCK, 60},
59 {1920, 1080, RES_1920X1080_60HZ_PIXCLOCK, 60},
60 {1400, 1050, RES_1400X1050_60HZ_PIXCLOCK, 60},
61 {1400, 1050, RES_1400X1050_75HZ_PIXCLOCK, 75},
62 {1368, 768, RES_1368X768_60HZ_PIXCLOCK, 60},
63 {960, 600, RES_960X600_60HZ_PIXCLOCK, 60},
64 {1000, 600, RES_1000X600_60HZ_PIXCLOCK, 60},
65 {1024, 576, RES_1024X576_60HZ_PIXCLOCK, 60},
66 {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60},
67 {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60},
68 {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60},
69 {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60},
70 {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50},
71 {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50},
72 {1360, 768, RES_1360X768_60HZ_PIXCLOCK, 60},
73 {1366, 768, RES_1366X768_50HZ_PIXCLOCK, 50},
74 {1366, 768, RES_1366X768_60HZ_PIXCLOCK, 60},
75 {1440, 900, RES_1440X900_60HZ_PIXCLOCK, 60},
76 {1440, 900, RES_1440X900_75HZ_PIXCLOCK, 75},
77 {1600, 900, RES_1600X900_60HZ_PIXCLOCK, 60},
78 {1600, 1024, RES_1600X1024_60HZ_PIXCLOCK, 60},
79 {1680, 1050, RES_1680X1050_60HZ_PIXCLOCK, 60},
80 {1680, 1050, RES_1680X1050_75HZ_PIXCLOCK, 75},
81 {1792, 1344, RES_1792X1344_60HZ_PIXCLOCK, 60},
82 {1856, 1392, RES_1856X1392_60HZ_PIXCLOCK, 60},
83 {1920, 1200, RES_1920X1200_60HZ_PIXCLOCK, 60},
84 {1920, 1440, RES_1920X1440_60HZ_PIXCLOCK, 60},
85 {1920, 1440, RES_1920X1440_75HZ_PIXCLOCK, 75},
86 {2048, 1536, RES_2048X1536_60HZ_PIXCLOCK, 60}
87};
88
89struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
90{VIASR, SR15, 0x02, 0x02},
91{VIASR, SR16, 0xBF, 0x08},
92{VIASR, SR17, 0xFF, 0x1F},
93{VIASR, SR18, 0xFF, 0x4E},
94{VIASR, SR1A, 0xFB, 0x08},
95{VIASR, SR1E, 0x0F, 0x01},
96{VIASR, SR2A, 0xFF, 0x00},
97{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
98{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
99{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
100{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
101{VIACR, CR32, 0xFF, 0x00},
102{VIACR, CR33, 0xFF, 0x00},
103{VIACR, CR34, 0xFF, 0x00},
104{VIACR, CR35, 0xFF, 0x00},
105{VIACR, CR36, 0x08, 0x00},
106{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
107{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
108{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
109{VIACR, CR69, 0xFF, 0x00},
110{VIACR, CR6A, 0xFF, 0x40},
111{VIACR, CR6B, 0xFF, 0x00},
112{VIACR, CR6C, 0xFF, 0x00},
113{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
114{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
115{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
116{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
117{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
118{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
119{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
120{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
121{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
122{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
123{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
124{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
125{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
126{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
127{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
128{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
129{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
130{VIACR, CR8B, 0xFF, 0x69}, /* LCD Power Sequence Control 0 */
131{VIACR, CR8C, 0xFF, 0x57}, /* LCD Power Sequence Control 1 */
132{VIACR, CR8D, 0xFF, 0x00}, /* LCD Power Sequence Control 2 */
133{VIACR, CR8E, 0xFF, 0x7B}, /* LCD Power Sequence Control 3 */
134{VIACR, CR8F, 0xFF, 0x03}, /* LCD Power Sequence Control 4 */
135{VIACR, CR90, 0xFF, 0x30}, /* LCD Power Sequence Control 5 */
136{VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
137{VIACR, CR96, 0xFF, 0x00},
138{VIACR, CR97, 0xFF, 0x00},
139{VIACR, CR99, 0xFF, 0x00},
140{VIACR, CR9B, 0xFF, 0x00}
141};
142
143/* Video Mode Table for VT3314 chipset*/
144/* Common Setting for Video Mode */
145struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
146{VIASR, SR15, 0x02, 0x02},
147{VIASR, SR16, 0xBF, 0x08},
148{VIASR, SR17, 0xFF, 0x1F},
149{VIASR, SR18, 0xFF, 0x4E},
150{VIASR, SR1A, 0xFB, 0x82},
151{VIASR, SR1B, 0xFF, 0xF0},
152{VIASR, SR1F, 0xFF, 0x00},
153{VIASR, SR1E, 0xFF, 0x01},
154{VIASR, SR22, 0xFF, 0x1F},
155{VIASR, SR2A, 0x0F, 0x00},
156{VIASR, SR2E, 0xFF, 0xFF},
157{VIASR, SR3F, 0xFF, 0xFF},
158{VIASR, SR40, 0xF7, 0x00},
159{VIASR, CR30, 0xFF, 0x04},
160{VIACR, CR32, 0xFF, 0x00},
161{VIACR, CR33, 0x7F, 0x00},
162{VIACR, CR34, 0xFF, 0x00},
163{VIACR, CR35, 0xFF, 0x00},
164{VIACR, CR36, 0xFF, 0x31},
165{VIACR, CR41, 0xFF, 0x80},
166{VIACR, CR42, 0xFF, 0x00},
167{VIACR, CR55, 0x80, 0x00},
168{VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/
169{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
170{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
171{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
172{VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
173{VIACR, CR69, 0xFF, 0x00},
174{VIACR, CR6A, 0xFD, 0x40},
175{VIACR, CR6B, 0xFF, 0x00},
176{VIACR, CR6C, 0xFF, 0x00},
177{VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */
178{VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */
179{VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */
180{VIACR, CR9F, 0x03, 0x00}, /* LCD scaling Factor */
181{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
182{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
183{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
184{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
185{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
186{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
187{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
188{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
189{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
190{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
191{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
192{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
193{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
194{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
195{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
196{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
197{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
198{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
199{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
200{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
201{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
202{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
203{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
204{VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
205{VIACR, CR96, 0xFF, 0x00},
206{VIACR, CR97, 0xFF, 0x00},
207{VIACR, CR99, 0xFF, 0x00},
208{VIACR, CR9B, 0xFF, 0x00},
209{VIACR, CR9D, 0xFF, 0x80},
210{VIACR, CR9E, 0xFF, 0x80}
211};
212
213struct io_reg KM400_ModeXregs[] = {
214 {VIASR, SR10, 0xFF, 0x01}, /* Unlock Register */
215 {VIASR, SR16, 0xFF, 0x08}, /* Display FIFO threshold Control */
216 {VIASR, SR17, 0xFF, 0x1F}, /* Display FIFO Control */
217 {VIASR, SR18, 0xFF, 0x4E}, /* GFX PREQ threshold */
218 {VIASR, SR1A, 0xFF, 0x0a}, /* GFX PREQ threshold */
219 {VIASR, SR1F, 0xFF, 0x00}, /* Memory Control 0 */
220 {VIASR, SR1B, 0xFF, 0xF0}, /* Power Management Control 0 */
221 {VIASR, SR1E, 0xFF, 0x01}, /* Power Management Control */
222 {VIASR, SR20, 0xFF, 0x00}, /* Sequencer Arbiter Control 0 */
223 {VIASR, SR21, 0xFF, 0x00}, /* Sequencer Arbiter Control 1 */
224 {VIASR, SR22, 0xFF, 0x1F}, /* Display Arbiter Control 1 */
225 {VIASR, SR2A, 0xFF, 0x00}, /* Power Management Control 5 */
226 {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */
227 {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */
228 {VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
229 {VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
230 {VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
231 {VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
232 {VIACR, CR33, 0xFF, 0x00},
233 {VIACR, CR55, 0x80, 0x00},
234 {VIACR, CR5D, 0x80, 0x00},
235 {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */
236 {VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
237 {VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
238 {VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
239 {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
240 {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */
241 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
242 {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
243 {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
244 {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
245 {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
246 {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
247 {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
248 {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
249 {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
250 {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
251 {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
252 {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
253 {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
254 {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
255 {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
256 {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
257 {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
258 {VIACR, CR8B, 0xFF, 0x2D}, /* LCD Power Sequence Control 0 */
259 {VIACR, CR8C, 0xFF, 0x2D}, /* LCD Power Sequence Control 1 */
260 {VIACR, CR8D, 0xFF, 0xC8}, /* LCD Power Sequence Control 2 */
261 {VIACR, CR8E, 0xFF, 0x36}, /* LCD Power Sequence Control 3 */
262 {VIACR, CR8F, 0xFF, 0x00}, /* LCD Power Sequence Control 4 */
263 {VIACR, CR90, 0xFF, 0x10}, /* LCD Power Sequence Control 5 */
264 {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
265 {VIACR, CR96, 0xFF, 0x03}, /* DVP0 ; DVP0 Clock Skew */
266 {VIACR, CR97, 0xFF, 0x03}, /* DFP high ; DFPH Clock Skew */
267 {VIACR, CR99, 0xFF, 0x03}, /* DFP low ; DFPL Clock Skew*/
268 {VIACR, CR9B, 0xFF, 0x07} /* DVI on DVP1 ; DVP1 Clock Skew*/
269};
270
271/* For VT3324: Common Setting for Video Mode */
272struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
273{VIASR, SR15, 0x02, 0x02},
274{VIASR, SR16, 0xBF, 0x08},
275{VIASR, SR17, 0xFF, 0x1F},
276{VIASR, SR18, 0xFF, 0x4E},
277{VIASR, SR1A, 0xFB, 0x08},
278{VIASR, SR1B, 0xFF, 0xF0},
279{VIASR, SR1E, 0xFF, 0x01},
280{VIASR, SR2A, 0xFF, 0x00},
281{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
282{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
283{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
284{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
285{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
286{VIACR, CR32, 0xFF, 0x00},
287{VIACR, CR33, 0xFF, 0x00},
288{VIACR, CR34, 0xFF, 0x00},
289{VIACR, CR35, 0xFF, 0x00},
290{VIACR, CR36, 0x08, 0x00},
291{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
292{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
293{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
294{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
295{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
296{VIACR, CR69, 0xFF, 0x00},
297{VIACR, CR6A, 0xFF, 0x40},
298{VIACR, CR6B, 0xFF, 0x00},
299{VIACR, CR6C, 0xFF, 0x00},
300{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
301{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
302{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
303{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
304{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
305{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
306{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
307{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
308{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
309{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
310{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
311{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
312{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
313{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
314{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
315{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
316{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
317{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
318{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
319{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
320{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
321{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
322{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
323{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
324{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
325{VIACR, CR96, 0xFF, 0x00},
326{VIACR, CR97, 0xFF, 0x00},
327{VIACR, CR99, 0xFF, 0x00},
328{VIACR, CR9B, 0xFF, 0x00},
329{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
330};
331
332/* For VT3353: Common Setting for Video Mode */
333struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
334{VIASR, SR15, 0x02, 0x02},
335{VIASR, SR16, 0xBF, 0x08},
336{VIASR, SR17, 0xFF, 0x1F},
337{VIASR, SR18, 0xFF, 0x4E},
338{VIASR, SR1A, 0xFB, 0x08},
339{VIASR, SR1B, 0xFF, 0xF0},
340{VIASR, SR1E, 0xFF, 0x01},
341{VIASR, SR2A, 0xFF, 0x00},
342{VIASR, SR2D, 0xFF, 0xFF}, /* VCK and LCK PLL power on. */
343{VIACR, CR0A, 0xFF, 0x1E}, /* Cursor Start */
344{VIACR, CR0B, 0xFF, 0x00}, /* Cursor End */
345{VIACR, CR0E, 0xFF, 0x00}, /* Cursor Location High */
346{VIACR, CR0F, 0xFF, 0x00}, /* Cursor Localtion Low */
347{VIACR, CR32, 0xFF, 0x00},
348{VIACR, CR33, 0xFF, 0x00},
349{VIACR, CR34, 0xFF, 0x00},
350{VIACR, CR35, 0xFF, 0x00},
351{VIACR, CR36, 0x08, 0x00},
352{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
353{VIACR, CR62, 0xFF, 0x00}, /* Secondary Display Starting Address */
354{VIACR, CR63, 0xFF, 0x00}, /* Secondary Display Starting Address */
355{VIACR, CR64, 0xFF, 0x00}, /* Secondary Display Starting Address */
356{VIACR, CRA3, 0xFF, 0x00}, /* Secondary Display Starting Address */
357{VIACR, CR69, 0xFF, 0x00},
358{VIACR, CR6A, 0xFF, 0x40},
359{VIACR, CR6B, 0xFF, 0x00},
360{VIACR, CR6C, 0xFF, 0x00},
361{VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
362{VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
363{VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
364{VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
365{VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
366{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
367{VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
368{VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
369{VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
370{VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
371{VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
372{VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
373{VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
374{VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
375{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
376{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
377{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
378{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
379{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
380{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
381{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
382{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
383{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
384{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
385{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
386{VIACR, CR96, 0xFF, 0x00},
387{VIACR, CR97, 0xFF, 0x00},
388{VIACR, CR99, 0xFF, 0x00},
389{VIACR, CR9B, 0xFF, 0x00},
390{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
391};
392
393/* Video Mode Table */
394/* Common Setting for Video Mode */
395struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
396{VIASR, SR2A, 0x0F, 0x00},
397{VIASR, SR15, 0x02, 0x02},
398{VIASR, SR16, 0xBF, 0x08},
399{VIASR, SR17, 0xFF, 0x1F},
400{VIASR, SR18, 0xFF, 0x4E},
401{VIASR, SR1A, 0xFB, 0x08},
402
403{VIACR, CR32, 0xFF, 0x00},
404{VIACR, CR34, 0xFF, 0x00},
405{VIACR, CR35, 0xFF, 0x00},
406{VIACR, CR36, 0x08, 0x00},
407{VIACR, CR6A, 0xFF, 0x80},
408{VIACR, CR6A, 0xFF, 0xC0},
409
410{VIACR, CR55, 0x80, 0x00},
411{VIACR, CR5D, 0x80, 0x00},
412
413{VIAGR, GR20, 0xFF, 0x00},
414{VIAGR, GR21, 0xFF, 0x00},
415{VIAGR, GR22, 0xFF, 0x00},
416 /* LCD Parameters */
417{VIACR, CR7A, 0xFF, 0x01}, /* LCD Parameter 1 */
418{VIACR, CR7B, 0xFF, 0x02}, /* LCD Parameter 2 */
419{VIACR, CR7C, 0xFF, 0x03}, /* LCD Parameter 3 */
420{VIACR, CR7D, 0xFF, 0x04}, /* LCD Parameter 4 */
421{VIACR, CR7E, 0xFF, 0x07}, /* LCD Parameter 5 */
422{VIACR, CR7F, 0xFF, 0x0A}, /* LCD Parameter 6 */
423{VIACR, CR80, 0xFF, 0x0D}, /* LCD Parameter 7 */
424{VIACR, CR81, 0xFF, 0x13}, /* LCD Parameter 8 */
425{VIACR, CR82, 0xFF, 0x16}, /* LCD Parameter 9 */
426{VIACR, CR83, 0xFF, 0x19}, /* LCD Parameter 10 */
427{VIACR, CR84, 0xFF, 0x1C}, /* LCD Parameter 11 */
428{VIACR, CR85, 0xFF, 0x1D}, /* LCD Parameter 12 */
429{VIACR, CR86, 0xFF, 0x1E}, /* LCD Parameter 13 */
430{VIACR, CR87, 0xFF, 0x1F}, /* LCD Parameter 14 */
431
432};
433
434/* Mode:1024X768 */
435struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
436{VIASR, 0x18, 0xFF, 0x4C}
437};
438
439struct patch_table res_patch_table[] = {
440 {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768}
441};
442
443/* struct VPITTable {
444 unsigned char Misc;
445 unsigned char SR[StdSR];
446 unsigned char CR[StdCR];
447 unsigned char GR[StdGR];
448 unsigned char AR[StdAR];
449 };*/
450
451struct VPITTable VPIT = {
452 /* Msic */
453 0xC7,
454 /* Sequencer */
455 {0x01, 0x0F, 0x00, 0x0E},
456 /* Graphic Controller */
457 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
458 /* Attribute Controller */
459 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
460 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
461 0x01, 0x00, 0x0F, 0x00}
462};
463
464/********************/
465/* Mode Table */
466/********************/
467
468/* 480x640 */
469struct crt_mode_table CRTM480x640[] = {
470 /* r_rate, vclk, hsp, vsp */
471 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
472 {REFRESH_60, CLK_25_175M, M480X640_R60_HSP, M480X640_R60_VSP,
473 {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/
474};
475
476/* 640x480*/
477struct crt_mode_table CRTM640x480[] = {
478 /*r_rate,vclk,hsp,vsp */
479 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
480 {REFRESH_60, CLK_25_175M, M640X480_R60_HSP, M640X480_R60_VSP,
481 {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
482 {REFRESH_75, CLK_31_500M, M640X480_R75_HSP, M640X480_R75_VSP,
483 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
484 {REFRESH_85, CLK_36_000M, M640X480_R85_HSP, M640X480_R85_VSP,
485 {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} },
486 {REFRESH_100, CLK_43_163M, M640X480_R100_HSP, M640X480_R100_VSP,
487 {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/
488 {REFRESH_120, CLK_52_406M, M640X480_R120_HSP,
489 M640X480_R120_VSP,
490 {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481,
491 3} } /*GTF*/
492};
493
494/*720x480 (GTF)*/
495struct crt_mode_table CRTM720x480[] = {
496 /*r_rate,vclk,hsp,vsp */
497 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
498 {REFRESH_60, CLK_26_880M, M720X480_R60_HSP, M720X480_R60_VSP,
499 {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} }
500
501};
502
503/*720x576 (GTF)*/
504struct crt_mode_table CRTM720x576[] = {
505 /*r_rate,vclk,hsp,vsp */
506 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
507 {REFRESH_60, CLK_32_668M, M720X576_R60_HSP, M720X576_R60_VSP,
508 {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} }
509};
510
511/* 800x480 (CVT) */
512struct crt_mode_table CRTM800x480[] = {
513 /* r_rate, vclk, hsp, vsp */
514 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
515 {REFRESH_60, CLK_29_581M, M800X480_R60_HSP, M800X480_R60_VSP,
516 {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} }
517};
518
519/* 800x600*/
520struct crt_mode_table CRTM800x600[] = {
521 /*r_rate,vclk,hsp,vsp */
522 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
523 {REFRESH_60, CLK_40_000M, M800X600_R60_HSP, M800X600_R60_VSP,
524 {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} },
525 {REFRESH_75, CLK_49_500M, M800X600_R75_HSP, M800X600_R75_VSP,
526 {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} },
527 {REFRESH_85, CLK_56_250M, M800X600_R85_HSP, M800X600_R85_VSP,
528 {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} },
529 {REFRESH_100, CLK_68_179M, M800X600_R100_HSP, M800X600_R100_VSP,
530 {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} },
531 {REFRESH_120, CLK_83_950M, M800X600_R120_HSP,
532 M800X600_R120_VSP,
533 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601,
534 3} }
535};
536
537/* 848x480 (CVT) */
538struct crt_mode_table CRTM848x480[] = {
539 /* r_rate, vclk, hsp, vsp */
540 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
541 {REFRESH_60, CLK_31_500M, M848X480_R60_HSP, M848X480_R60_VSP,
542 {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} }
543};
544
545/*856x480 (GTF) convert to 852x480*/
546struct crt_mode_table CRTM852x480[] = {
547 /*r_rate,vclk,hsp,vsp */
548 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
549 {REFRESH_60, CLK_31_728M, M852X480_R60_HSP, M852X480_R60_VSP,
550 {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
551};
552
553/*1024x512 (GTF)*/
554struct crt_mode_table CRTM1024x512[] = {
555 /*r_rate,vclk,hsp,vsp */
556 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
557 {REFRESH_60, CLK_41_291M, M1024X512_R60_HSP, M1024X512_R60_VSP,
558 {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
559
560};
561
562/* 1024x600*/
563struct crt_mode_table CRTM1024x600[] = {
564 /*r_rate,vclk,hsp,vsp */
565 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
566 {REFRESH_60, CLK_48_875M, M1024X600_R60_HSP, M1024X600_R60_VSP,
567 {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
568};
569
570/* 1024x768*/
571struct crt_mode_table CRTM1024x768[] = {
572 /*r_rate,vclk,hsp,vsp */
573 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
574 {REFRESH_60, CLK_65_000M, M1024X768_R60_HSP, M1024X768_R60_VSP,
575 {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
576 {REFRESH_75, CLK_78_750M, M1024X768_R75_HSP, M1024X768_R75_VSP,
577 {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
578 {REFRESH_85, CLK_94_500M, M1024X768_R85_HSP, M1024X768_R85_VSP,
579 {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
580 {REFRESH_100, CLK_113_309M, M1024X768_R100_HSP, M1024X768_R100_VSP,
581 {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
582};
583
584/* 1152x864*/
585struct crt_mode_table CRTM1152x864[] = {
586 /*r_rate,vclk,hsp,vsp */
587 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
588 {REFRESH_75, CLK_108_000M, M1152X864_R75_HSP, M1152X864_R75_VSP,
589 {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
590
591};
592
593/* 1280x720 (HDMI 720P)*/
594struct crt_mode_table CRTM1280x720[] = {
595 /*r_rate,vclk,hsp,vsp */
596 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
597 {REFRESH_60, CLK_74_481M, M1280X720_R60_HSP, M1280X720_R60_VSP,
598 {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
599 {REFRESH_50, CLK_60_466M, M1280X720_R50_HSP, M1280X720_R50_VSP,
600 {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
601};
602
603/*1280x768 (GTF)*/
604struct crt_mode_table CRTM1280x768[] = {
605 /*r_rate,vclk,hsp,vsp */
606 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
607 {REFRESH_60, CLK_80_136M, M1280X768_R60_HSP, M1280X768_R60_VSP,
608 {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
609 {REFRESH_50, CLK_65_178M, M1280X768_R50_HSP, M1280X768_R50_VSP,
610 {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
611};
612
613/* 1280x800 (CVT) */
614struct crt_mode_table CRTM1280x800[] = {
615 /* r_rate, vclk, hsp, vsp */
616 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
617 {REFRESH_60, CLK_83_375M, M1280X800_R60_HSP, M1280X800_R60_VSP,
618 {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
619};
620
621/*1280x960*/
622struct crt_mode_table CRTM1280x960[] = {
623 /*r_rate,vclk,hsp,vsp */
624 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
625 {REFRESH_60, CLK_108_000M, M1280X960_R60_HSP, M1280X960_R60_VSP,
626 {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
627};
628
629/* 1280x1024*/
630struct crt_mode_table CRTM1280x1024[] = {
631 /*r_rate,vclk,,hsp,vsp */
632 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
633 {REFRESH_60, CLK_108_000M, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
634 {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
635 3} },
636 {REFRESH_75, CLK_135_000M, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
637 {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
638 3} },
639 {REFRESH_85, CLK_157_500M, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
640 {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
641};
642
643/* 1368x768 (GTF) */
644struct crt_mode_table CRTM1368x768[] = {
645 /* r_rate, vclk, hsp, vsp */
646 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
647 {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
648 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
649};
650
651/*1440x1050 (GTF)*/
652struct crt_mode_table CRTM1440x1050[] = {
653 /*r_rate,vclk,hsp,vsp */
654 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
655 {REFRESH_60, CLK_125_104M, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
656 {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
657};
658
659/* 1600x1200*/
660struct crt_mode_table CRTM1600x1200[] = {
661 /*r_rate,vclk,hsp,vsp */
662 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
663 {REFRESH_60, CLK_162_000M, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
664 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
665 3} },
666 {REFRESH_75, CLK_202_500M, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
667 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
668
669};
670
671/* 1680x1050 (CVT) */
672struct crt_mode_table CRTM1680x1050[] = {
673 /* r_rate, vclk, hsp, vsp */
674 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
675 {REFRESH_60, CLK_146_760M, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
676 {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
677 6} },
678 {REFRESH_75, CLK_187_000M, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
679 {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
680};
681
682/* 1680x1050 (CVT Reduce Blanking) */
683struct crt_mode_table CRTM1680x1050_RB[] = {
684 /* r_rate, vclk, hsp, vsp */
685 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
686 {REFRESH_60, CLK_119_000M, M1680x1050_RB_R60_HSP,
687 M1680x1050_RB_R60_VSP,
688 {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
689};
690
691/* 1920x1080 (CVT)*/
692struct crt_mode_table CRTM1920x1080[] = {
693 /*r_rate,vclk,hsp,vsp */
694 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
695 {REFRESH_60, CLK_172_798M, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
696 {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
697};
698
699/* 1920x1080 (CVT with Reduce Blanking) */
700struct crt_mode_table CRTM1920x1080_RB[] = {
701 /* r_rate, vclk, hsp, vsp */
702 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
703 {REFRESH_60, CLK_138_400M, M1920X1080_RB_R60_HSP,
704 M1920X1080_RB_R60_VSP,
705 {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
706};
707
708/* 1920x1440*/
709struct crt_mode_table CRTM1920x1440[] = {
710 /*r_rate,vclk,hsp,vsp */
711 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
712 {REFRESH_60, CLK_234_000M, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
713 {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
714 3} },
715 {REFRESH_75, CLK_297_500M, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
716 {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
717};
718
719/* 1400x1050 (CVT) */
720struct crt_mode_table CRTM1400x1050[] = {
721 /* r_rate, vclk, hsp, vsp */
722 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
723 {REFRESH_60, CLK_121_750M, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
724 {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
725 4} },
726 {REFRESH_75, CLK_156_000M, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
727 {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
728};
729
730/* 1400x1050 (CVT Reduce Blanking) */
731struct crt_mode_table CRTM1400x1050_RB[] = {
732 /* r_rate, vclk, hsp, vsp */
733 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
734 {REFRESH_60, CLK_101_000M, M1400X1050_RB_R60_HSP,
735 M1400X1050_RB_R60_VSP,
736 {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
737};
738
739/* 960x600 (CVT) */
740struct crt_mode_table CRTM960x600[] = {
741 /* r_rate, vclk, hsp, vsp */
742 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
743 {REFRESH_60, CLK_45_250M, M960X600_R60_HSP, M960X600_R60_VSP,
744 {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
745};
746
747/* 1000x600 (GTF) */
748struct crt_mode_table CRTM1000x600[] = {
749 /* r_rate, vclk, hsp, vsp */
750 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
751 {REFRESH_60, CLK_48_000M, M1000X600_R60_HSP, M1000X600_R60_VSP,
752 {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
753};
754
755/* 1024x576 (GTF) */
756struct crt_mode_table CRTM1024x576[] = {
757 /* r_rate, vclk, hsp, vsp */
758 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
759 {REFRESH_60, CLK_46_996M, M1024X576_R60_HSP, M1024X576_R60_VSP,
760 {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
761};
762
763/* 1088x612 (CVT) */
764struct crt_mode_table CRTM1088x612[] = {
765 /* r_rate, vclk, hsp, vsp */
766 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
767 {REFRESH_60, CLK_52_977M, M1088X612_R60_HSP, M1088X612_R60_VSP,
768 {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
769};
770
771/* 1152x720 (CVT) */
772struct crt_mode_table CRTM1152x720[] = {
773 /* r_rate, vclk, hsp, vsp */
774 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
775 {REFRESH_60, CLK_66_750M, M1152X720_R60_HSP, M1152X720_R60_VSP,
776 {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
777};
778
779/* 1200x720 (GTF) */
780struct crt_mode_table CRTM1200x720[] = {
781 /* r_rate, vclk, hsp, vsp */
782 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
783 {REFRESH_60, CLK_70_159M, M1200X720_R60_HSP, M1200X720_R60_VSP,
784 {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
785};
786
787/* 1280x600 (GTF) */
788struct crt_mode_table CRTM1280x600[] = {
789 /* r_rate, vclk, hsp, vsp */
790 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
791 {REFRESH_60, CLK_61_500M, M1280x600_R60_HSP, M1280x600_R60_VSP,
792 {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
793};
794
795/* 1360x768 (CVT) */
796struct crt_mode_table CRTM1360x768[] = {
797 /* r_rate, vclk, hsp, vsp */
798 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
799 {REFRESH_60, CLK_84_750M, M1360X768_R60_HSP, M1360X768_R60_VSP,
800 {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
801};
802
803/* 1360x768 (CVT Reduce Blanking) */
804struct crt_mode_table CRTM1360x768_RB[] = {
805 /* r_rate, vclk, hsp, vsp */
806 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
807 {REFRESH_60, CLK_72_000M, M1360X768_RB_R60_HSP,
808 M1360X768_RB_R60_VSP,
809 {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
810};
811
812/* 1366x768 (GTF) */
813struct crt_mode_table CRTM1366x768[] = {
814 /* r_rate, vclk, hsp, vsp */
815 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
816 {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
817 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
818 {REFRESH_50, CLK_69_924M, M1368X768_R50_HSP, M1368X768_R50_VSP,
819 {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
820};
821
822/* 1440x900 (CVT) */
823struct crt_mode_table CRTM1440x900[] = {
824 /* r_rate, vclk, hsp, vsp */
825 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
826 {REFRESH_60, CLK_106_500M, M1440X900_R60_HSP, M1440X900_R60_VSP,
827 {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
828 {REFRESH_75, CLK_136_700M, M1440X900_R75_HSP, M1440X900_R75_VSP,
829 {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
830};
831
832/* 1440x900 (CVT Reduce Blanking) */
833struct crt_mode_table CRTM1440x900_RB[] = {
834 /* r_rate, vclk, hsp, vsp */
835 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
836 {REFRESH_60, CLK_88_750M, M1440X900_RB_R60_HSP,
837 M1440X900_RB_R60_VSP,
838 {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
839};
840
841/* 1600x900 (CVT) */
842struct crt_mode_table CRTM1600x900[] = {
843 /* r_rate, vclk, hsp, vsp */
844 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
845 {REFRESH_60, CLK_118_840M, M1600X900_R60_HSP, M1600X900_R60_VSP,
846 {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
847};
848
849/* 1600x900 (CVT Reduce Blanking) */
850struct crt_mode_table CRTM1600x900_RB[] = {
851 /* r_rate, vclk, hsp, vsp */
852 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
853 {REFRESH_60, CLK_97_750M, M1600X900_RB_R60_HSP,
854 M1600X900_RB_R60_VSP,
855 {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
856};
857
858/* 1600x1024 (GTF) */
859struct crt_mode_table CRTM1600x1024[] = {
860 /* r_rate, vclk, hsp, vsp */
861 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
862 {REFRESH_60, CLK_136_700M, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
863 {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
864};
865
866/* 1792x1344 (DMT) */
867struct crt_mode_table CRTM1792x1344[] = {
868 /* r_rate, vclk, hsp, vsp */
869 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
870 {REFRESH_60, CLK_204_000M, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
871 {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
872};
873
874/* 1856x1392 (DMT) */
875struct crt_mode_table CRTM1856x1392[] = {
876 /* r_rate, vclk, hsp, vsp */
877 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
878 {REFRESH_60, CLK_218_500M, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
879 {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
880};
881
882/* 1920x1200 (CVT) */
883struct crt_mode_table CRTM1920x1200[] = {
884 /* r_rate, vclk, hsp, vsp */
885 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
886 {REFRESH_60, CLK_193_295M, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
887 {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
888};
889
890/* 1920x1200 (CVT with Reduce Blanking) */
891struct crt_mode_table CRTM1920x1200_RB[] = {
892 /* r_rate, vclk, hsp, vsp */
893 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
894 {REFRESH_60, CLK_153_920M, M1920X1200_RB_R60_HSP,
895 M1920X1200_RB_R60_VSP,
896 {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
897};
898
899/* 2048x1536 (CVT) */
900struct crt_mode_table CRTM2048x1536[] = {
901 /* r_rate, vclk, hsp, vsp */
902 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
903 {REFRESH_60, CLK_267_250M, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
904 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
905};
906
907/* Video Mode Table */
908/* struct VideoModeTable {*/
909/* int ModeIndex;*/
910/* struct crt_mode_table *crtc;*/
911/* int mode_array;*/
912/* };*/
913struct VideoModeTable CLE266Modes[] = {
914 /* Display : 480x640 (GTF) */
915 {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)},
916
917 /* Display : 640x480 */
918 {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)},
919
920 /* Display : 720x480 (GTF) */
921 {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)},
922
923 /* Display : 720x576 (GTF) */
924 {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)},
925
926 /* Display : 800x600 */
927 {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)},
928
929 /* Display : 800x480 (CVT) */
930 {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)},
931
932 /* Display : 848x480 (CVT) */
933 {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)},
934
935 /* Display : 852x480 (GTF) */
936 {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)},
937
938 /* Display : 1024x512 (GTF) */
939 {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
940
941 /* Display : 1024x600 */
942 {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
943
944 /* Display : 1024x576 (GTF) */
945 /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */
946
947 /* Display : 1024x768 */
948 {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
949
950 /* Display : 1152x864 */
951 {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
952
953 /* Display : 1280x768 (GTF) */
954 {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
955
956 /* Display : 960x600 (CVT) */
957 {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)},
958
959 /* Display : 1000x600 (GTF) */
960 {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
961
962 /* Display : 1024x576 (GTF) */
963 {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
964
965 /* Display : 1088x612 (GTF) */
966 {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
967
968 /* Display : 1152x720 (CVT) */
969 {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
970
971 /* Display : 1200x720 (GTF) */
972 {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
973
974 /* Display : 1280x600 (GTF) */
975 {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
976
977 /* Display : 1280x800 (CVT) */
978 {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
979
980 /* Display : 1280x800 (GTF) */
981 /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */
982
983 /* Display : 1280x960 */
984 {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
985
986 /* Display : 1280x1024 */
987 {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
988
989 /* Display : 1360x768 (CVT) */
990 {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
991
992 /* Display : 1360x768 (CVT Reduce Blanking) */
993 {VIA_RES_1360X768_RB, CRTM1360x768_RB,
994 ARRAY_SIZE(CRTM1360x768_RB)},
995
996 /* Display : 1366x768 */
997 {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
998
999 /* Display : 1368x768 (GTF) */
1000 /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */
1001 /* Display : 1368x768 (GTF) */
1002 {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
1003
1004 /* Display : 1440x900 (CVT) */
1005 {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
1006
1007 /* Display : 1440x900 (CVT Reduce Blanking) */
1008 {VIA_RES_1440X900_RB, CRTM1440x900_RB,
1009 ARRAY_SIZE(CRTM1440x900_RB)},
1010
1011 /* Display : 1440x1050 (GTF) */
1012 {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
1013
1014 /* Display : 1400x1050 (CVT Reduce Blanking) */
1015 {VIA_RES_1400X1050_RB, CRTM1400x1050_RB,
1016 ARRAY_SIZE(CRTM1400x1050_RB)},
1017
1018 /* Display : 1600x900 (CVT) */
1019 {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
1020
1021 /* Display : 1600x900 (CVT Reduce Blanking) */
1022 {VIA_RES_1600X900_RB, CRTM1600x900_RB,
1023 ARRAY_SIZE(CRTM1600x900_RB)},
1024
1025 /* Display : 1600x1024 (GTF) */
1026 {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
1027
1028 /* Display : 1600x1200 */
1029 {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
1030
1031 /* Display : 1680x1050 (CVT) */
1032 {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
1033
1034 /* Display : 1680x1050 (CVT Reduce Blanking) */
1035 {VIA_RES_1680X1050_RB, CRTM1680x1050_RB,
1036 ARRAY_SIZE(CRTM1680x1050_RB)},
1037
1038 /* Display : 1792x1344 (DMT) */
1039 {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
1040
1041 /* Display : 1856x1392 (DMT) */
1042 {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
1043
1044 /* Display : 1920x1440 */
1045 {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
1046
1047 /* Display : 2048x1536 */
1048 {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
1049
1050 /* Display : 1280x720 */
1051 {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
1052
1053 /* Display : 1920x1080 (CVT) */
1054 {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
1055
1056 /* Display : 1920x1080 (CVT Reduce Blanking) */
1057 {VIA_RES_1920X1080_RB, CRTM1920x1080_RB,
1058 ARRAY_SIZE(CRTM1920x1080_RB)},
1059
1060 /* Display : 1920x1200 (CVT) */
1061 {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
1062
1063 /* Display : 1920x1200 (CVT Reduce Blanking) */
1064 {VIA_RES_1920X1200_RB, CRTM1920x1200_RB,
1065 ARRAY_SIZE(CRTM1920x1200_RB)},
1066
1067 /* Display : 1400x1050 (CVT) */
1068 {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
1069};
1070struct crt_mode_table CEAM1280x720[] = {
1071 {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
1072 M1280X720_CEA_R60_VSP,
1073 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
1074 {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
1075};
1076struct crt_mode_table CEAM1920x1080[] = {
1077 {REFRESH_60, CLK_148_500M, M1920X1080_CEA_R60_HSP,
1078 M1920X1080_CEA_R60_VSP,
1079 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
1080 {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
1081};
1082struct VideoModeTable CEA_HDMI_Modes[] = {
1083 /* Display : 1280x720 */
1084 {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
1085 {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
1086};
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
new file mode 100644
index 000000000000..1a5de50a23a2
--- /dev/null
+++ b/drivers/video/via/viamode.h
@@ -0,0 +1,177 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __VIAMODE_H__
23#define __VIAMODE_H__
24
25#include "global.h"
26
27struct VPITTable {
28 unsigned char Misc;
29 unsigned char SR[StdSR];
30 unsigned char GR[StdGR];
31 unsigned char AR[StdAR];
32};
33
34struct VideoModeTable {
35 int ModeIndex;
36 struct crt_mode_table *crtc;
37 int mode_array;
38};
39
40struct patch_table {
41 int mode_index;
42 int table_length;
43 struct io_reg *io_reg_table;
44};
45
46struct res_map_refresh {
47 int hres;
48 int vres;
49 int pixclock;
50 int vmode_refresh;
51};
52
53#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl)
54#define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes)
55#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs)
56#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs)
57#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs)
58#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs)
59#define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs)
60#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs)
61#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table)
62#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes)
63
64/********************/
65/* Mode Table */
66/********************/
67
68/* 480x640 */
69extern struct crt_mode_table CRTM480x640[1];
70/* 640x480*/
71extern struct crt_mode_table CRTM640x480[5];
72/*720x480 (GTF)*/
73extern struct crt_mode_table CRTM720x480[1];
74/*720x576 (GTF)*/
75extern struct crt_mode_table CRTM720x576[1];
76/* 800x480 (CVT) */
77extern struct crt_mode_table CRTM800x480[1];
78/* 800x600*/
79extern struct crt_mode_table CRTM800x600[5];
80/* 848x480 (CVT) */
81extern struct crt_mode_table CRTM848x480[1];
82/*856x480 (GTF) convert to 852x480*/
83extern struct crt_mode_table CRTM852x480[1];
84/*1024x512 (GTF)*/
85extern struct crt_mode_table CRTM1024x512[1];
86/* 1024x600*/
87extern struct crt_mode_table CRTM1024x600[1];
88/* 1024x768*/
89extern struct crt_mode_table CRTM1024x768[4];
90/* 1152x864*/
91extern struct crt_mode_table CRTM1152x864[1];
92/* 1280x720 (HDMI 720P)*/
93extern struct crt_mode_table CRTM1280x720[2];
94/*1280x768 (GTF)*/
95extern struct crt_mode_table CRTM1280x768[2];
96/* 1280x800 (CVT) */
97extern struct crt_mode_table CRTM1280x800[1];
98/*1280x960*/
99extern struct crt_mode_table CRTM1280x960[1];
100/* 1280x1024*/
101extern struct crt_mode_table CRTM1280x1024[3];
102/* 1368x768 (GTF) */
103extern struct crt_mode_table CRTM1368x768[1];
104/*1440x1050 (GTF)*/
105extern struct crt_mode_table CRTM1440x1050[1];
106/* 1600x1200*/
107extern struct crt_mode_table CRTM1600x1200[2];
108/* 1680x1050 (CVT) */
109extern struct crt_mode_table CRTM1680x1050[2];
110/* 1680x1050 (CVT Reduce Blanking) */
111extern struct crt_mode_table CRTM1680x1050_RB[1];
112/* 1920x1080 (CVT)*/
113extern struct crt_mode_table CRTM1920x1080[1];
114/* 1920x1080 (CVT with Reduce Blanking) */
115extern struct crt_mode_table CRTM1920x1080_RB[1];
116/* 1920x1440*/
117extern struct crt_mode_table CRTM1920x1440[2];
118/* 1400x1050 (CVT) */
119extern struct crt_mode_table CRTM1400x1050[2];
120/* 1400x1050 (CVT Reduce Blanking) */
121extern struct crt_mode_table CRTM1400x1050_RB[1];
122/* 960x600 (CVT) */
123extern struct crt_mode_table CRTM960x600[1];
124/* 1000x600 (GTF) */
125extern struct crt_mode_table CRTM1000x600[1];
126/* 1024x576 (GTF) */
127extern struct crt_mode_table CRTM1024x576[1];
128/* 1088x612 (CVT) */
129extern struct crt_mode_table CRTM1088x612[1];
130/* 1152x720 (CVT) */
131extern struct crt_mode_table CRTM1152x720[1];
132/* 1200x720 (GTF) */
133extern struct crt_mode_table CRTM1200x720[1];
134/* 1280x600 (GTF) */
135extern struct crt_mode_table CRTM1280x600[1];
136/* 1360x768 (CVT) */
137extern struct crt_mode_table CRTM1360x768[1];
138/* 1360x768 (CVT Reduce Blanking) */
139extern struct crt_mode_table CRTM1360x768_RB[1];
140/* 1366x768 (GTF) */
141extern struct crt_mode_table CRTM1366x768[2];
142/* 1440x900 (CVT) */
143extern struct crt_mode_table CRTM1440x900[2];
144/* 1440x900 (CVT Reduce Blanking) */
145extern struct crt_mode_table CRTM1440x900_RB[1];
146/* 1600x900 (CVT) */
147extern struct crt_mode_table CRTM1600x900[1];
148/* 1600x900 (CVT Reduce Blanking) */
149extern struct crt_mode_table CRTM1600x900_RB[1];
150/* 1600x1024 (GTF) */
151extern struct crt_mode_table CRTM1600x1024[1];
152/* 1792x1344 (DMT) */
153extern struct crt_mode_table CRTM1792x1344[1];
154/* 1856x1392 (DMT) */
155extern struct crt_mode_table CRTM1856x1392[1];
156/* 1920x1200 (CVT) */
157extern struct crt_mode_table CRTM1920x1200[1];
158/* 1920x1200 (CVT with Reduce Blanking) */
159extern struct crt_mode_table CRTM1920x1200_RB[1];
160/* 2048x1536 (CVT) */
161extern struct crt_mode_table CRTM2048x1536[1];
162extern struct VideoModeTable CLE266Modes[47];
163extern struct crt_mode_table CEAM1280x720[1];
164extern struct crt_mode_table CEAM1920x1080[1];
165extern struct VideoModeTable CEA_HDMI_Modes[2];
166
167extern struct res_map_refresh res_map_refresh_tbl[61];
168extern struct io_reg CN400_ModeXregs[52];
169extern struct io_reg CN700_ModeXregs[66];
170extern struct io_reg KM400_ModeXregs[55];
171extern struct io_reg CX700_ModeXregs[58];
172extern struct io_reg VX800_ModeXregs[58];
173extern struct io_reg CLE266_ModeXregs[32];
174extern struct io_reg PM1024x768[2];
175extern struct patch_table res_patch_table[1];
176extern struct VPITTable VPIT;
177#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
new file mode 100644
index 000000000000..322a9f993550
--- /dev/null
+++ b/drivers/video/via/vt1636.c
@@ -0,0 +1,306 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
25 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
26 u8 index)
27{
28 u8 data;
29
30 viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
31 viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data);
32
33 return data;
34}
35
36void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
37 *plvds_setting_info, struct lvds_chip_information
38 *plvds_chip_info, struct IODATA io_data)
39{
40 int index, data;
41
42 viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
43
44 index = io_data.Index;
45 data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
46 index);
47 data = (data & (~io_data.Mask)) | io_data.Data;
48
49 viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data);
50}
51
52void viafb_init_lvds_vt1636(struct lvds_setting_information
53 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
54{
55 int reg_num, i;
56
57 /* Common settings: */
58 reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636);
59
60 for (i = 0; i < reg_num; i++) {
61 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
62 plvds_chip_info,
63 COMMON_INIT_TBL_VT1636[i]);
64 }
65
66 /* Input Data Mode Select */
67 if (plvds_setting_info->device_lcd_dualedge) {
68 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
69 plvds_chip_info,
70 DUAL_CHANNEL_ENABLE_TBL_VT1636[0]);
71 } else {
72 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
73 plvds_chip_info,
74 SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
75 }
76
77 if (plvds_setting_info->LCDDithering) {
78 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
79 plvds_chip_info,
80 DITHERING_ENABLE_TBL_VT1636[0]);
81 } else {
82 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
83 plvds_chip_info,
84 DITHERING_DISABLE_TBL_VT1636[0]);
85 }
86}
87
88void viafb_enable_lvds_vt1636(struct lvds_setting_information
89 *plvds_setting_info,
90 struct lvds_chip_information *plvds_chip_info)
91{
92
93 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
94 VDD_ON_TBL_VT1636[0]);
95
96 /* Pad on: */
97 switch (plvds_chip_info->output_interface) {
98 case INTERFACE_DVP0:
99 {
100 viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
101 break;
102 }
103
104 case INTERFACE_DVP1:
105 {
106 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
107 break;
108 }
109
110 case INTERFACE_DFP_LOW:
111 {
112 viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
113 break;
114 }
115
116 case INTERFACE_DFP_HIGH:
117 {
118 viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
119 break;
120 }
121
122 }
123}
124
125void viafb_disable_lvds_vt1636(struct lvds_setting_information
126 *plvds_setting_info,
127 struct lvds_chip_information *plvds_chip_info)
128{
129
130 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
131 VDD_OFF_TBL_VT1636[0]);
132
133 /* Pad off: */
134 switch (plvds_chip_info->output_interface) {
135 case INTERFACE_DVP0:
136 {
137 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
138 break;
139 }
140
141 case INTERFACE_DVP1:
142 {
143 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
144 break;
145 }
146
147 case INTERFACE_DFP_LOW:
148 {
149 viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
150 break;
151 }
152
153 case INTERFACE_DFP_HIGH:
154 {
155 viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
156 break;
157 }
158
159 }
160}
161
162bool viafb_lvds_identify_vt1636(void)
163{
164 u8 Buffer[2];
165
166 DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
167
168 /* Sense VT1636 LVDS Transmiter */
169 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
170 VT1636_LVDS_I2C_ADDR;
171
172 /* Check vendor ID first: */
173 viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
174 lvds_chip_slave_addr,
175 0x00, &Buffer[0]);
176 viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
177 lvds_chip_slave_addr,
178 0x01, &Buffer[1]);
179
180 if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
181 return false;
182
183 /* Check Chip ID: */
184 viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
185 lvds_chip_slave_addr,
186 0x02, &Buffer[0]);
187 viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
188 lvds_chip_slave_addr,
189 0x03, &Buffer[1]);
190 if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
191 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
192 VT1636_LVDS;
193 return true;
194 }
195
196 return false;
197}
198
199static int get_clk_range_index(u32 Clk)
200{
201 if (Clk < DPA_CLK_30M)
202 return DPA_CLK_RANGE_30M;
203 else if (Clk < DPA_CLK_50M)
204 return DPA_CLK_RANGE_30_50M;
205 else if (Clk < DPA_CLK_70M)
206 return DPA_CLK_RANGE_50_70M;
207 else if (Clk < DPA_CLK_100M)
208 return DPA_CLK_RANGE_70_100M;
209 else if (Clk < DPA_CLK_150M)
210 return DPA_CLK_RANGE_100_150M;
211 else
212 return DPA_CLK_RANGE_150M;
213}
214
215static int get_lvds_dpa_setting_index(int panel_size_id,
216 struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
217 int tbl_size)
218{
219 int i;
220
221 for (i = 0; i < tbl_size; i++) {
222 if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
223 return i;
224
225 p_vt1636_dpasetting_tbl++;
226 }
227
228 return 0;
229}
230
231static void set_dpa_vt1636(struct lvds_setting_information
232 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
233 struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
234{
235 struct IODATA io_data;
236
237 io_data.Index = 0x09;
238 io_data.Mask = 0x1F;
239 io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
240 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
241 plvds_chip_info, io_data);
242
243 io_data.Index = 0x08;
244 io_data.Mask = 0x0F;
245 io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
246 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
247 io_data);
248}
249
250void viafb_vt1636_patch_skew_on_vt3324(
251 struct lvds_setting_information *plvds_setting_info,
252 struct lvds_chip_information *plvds_chip_info)
253{
254 int index, size;
255
256 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
257
258 /* Graphics DPA settings: */
259 index = get_clk_range_index(plvds_setting_info->vclk);
260 viafb_set_dpa_gfx(plvds_chip_info->output_interface,
261 &GFX_DPA_SETTING_TBL_VT3324[index]);
262
263 /* LVDS Transmitter DPA settings: */
264 size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324);
265 index =
266 get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
267 VT1636_DPA_SETTING_TBL_VT3324, size);
268 set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
269 &VT1636_DPA_SETTING_TBL_VT3324[index]);
270}
271
272void viafb_vt1636_patch_skew_on_vt3327(
273 struct lvds_setting_information *plvds_setting_info,
274 struct lvds_chip_information *plvds_chip_info)
275{
276 int index, size;
277
278 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
279
280 /* Graphics DPA settings: */
281 index = get_clk_range_index(plvds_setting_info->vclk);
282 viafb_set_dpa_gfx(plvds_chip_info->output_interface,
283 &GFX_DPA_SETTING_TBL_VT3327[index]);
284
285 /* LVDS Transmitter DPA settings: */
286 size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327);
287 index =
288 get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
289 VT1636_DPA_SETTING_TBL_VT3327, size);
290 set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
291 &VT1636_DPA_SETTING_TBL_VT3327[index]);
292}
293
294void viafb_vt1636_patch_skew_on_vt3364(
295 struct lvds_setting_information *plvds_setting_info,
296 struct lvds_chip_information *plvds_chip_info)
297{
298 int index;
299
300 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
301
302 /* Graphics DPA settings: */
303 index = get_clk_range_index(plvds_setting_info->vclk);
304 viafb_set_dpa_gfx(plvds_chip_info->output_interface,
305 &GFX_DPA_SETTING_TBL_VT3364[index]);
306}
diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h
new file mode 100644
index 000000000000..2a150c58c7ed
--- /dev/null
+++ b/drivers/video/via/vt1636.h
@@ -0,0 +1,44 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef _VT1636_H_
23#define _VT1636_H_
24#include "chip.h"
25bool viafb_lvds_identify_vt1636(void);
26void viafb_init_lvds_vt1636(struct lvds_setting_information
27 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
28void viafb_enable_lvds_vt1636(struct lvds_setting_information
29 *plvds_setting_info,
30 struct lvds_chip_information *plvds_chip_info);
31void viafb_disable_lvds_vt1636(struct lvds_setting_information
32 *plvds_setting_info,
33 struct lvds_chip_information *plvds_chip_info);
34void viafb_vt1636_patch_skew_on_vt3324(
35 struct lvds_setting_information *plvds_setting_info,
36 struct lvds_chip_information *plvds_chip_info);
37void viafb_vt1636_patch_skew_on_vt3327(
38 struct lvds_setting_information *plvds_setting_info,
39 struct lvds_chip_information *plvds_chip_info);
40void viafb_vt1636_patch_skew_on_vt3364(
41 struct lvds_setting_information *plvds_setting_info,
42 struct lvds_chip_information *plvds_chip_info);
43
44#endif
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 536ab11623f0..3df17dc8c3d7 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -12,7 +12,6 @@
12 * (http://davesdomain.org.uk/viafb/) 12 * (http://davesdomain.org.uk/viafb/)
13 */ 13 */
14 14
15#include <linux/version.h>
16#include <linux/module.h> 15#include <linux/module.h>
17#include <linux/kernel.h> 16#include <linux/kernel.h>
18#include <linux/errno.h> 17#include <linux/errno.h>
@@ -677,13 +676,13 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
677 676
678 rc = pci_enable_device(dev); 677 rc = pci_enable_device(dev);
679 if (rc < 0) { 678 if (rc < 0) {
680 dev_err(info->dev, "cannot enable PCI device\n"); 679 dev_err(info->device, "cannot enable PCI device\n");
681 goto err_enable_device; 680 goto err_enable_device;
682 } 681 }
683 682
684 rc = pci_request_regions(dev, "vt8623fb"); 683 rc = pci_request_regions(dev, "vt8623fb");
685 if (rc < 0) { 684 if (rc < 0) {
686 dev_err(info->dev, "cannot reserve framebuffer region\n"); 685 dev_err(info->device, "cannot reserve framebuffer region\n");
687 goto err_request_regions; 686 goto err_request_regions;
688 } 687 }
689 688
@@ -696,14 +695,14 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
696 info->screen_base = pci_iomap(dev, 0, 0); 695 info->screen_base = pci_iomap(dev, 0, 0);
697 if (! info->screen_base) { 696 if (! info->screen_base) {
698 rc = -ENOMEM; 697 rc = -ENOMEM;
699 dev_err(info->dev, "iomap for framebuffer failed\n"); 698 dev_err(info->device, "iomap for framebuffer failed\n");
700 goto err_iomap_1; 699 goto err_iomap_1;
701 } 700 }
702 701
703 par->mmio_base = pci_iomap(dev, 1, 0); 702 par->mmio_base = pci_iomap(dev, 1, 0);
704 if (! par->mmio_base) { 703 if (! par->mmio_base) {
705 rc = -ENOMEM; 704 rc = -ENOMEM;
706 dev_err(info->dev, "iomap for MMIO failed\n"); 705 dev_err(info->device, "iomap for MMIO failed\n");
707 goto err_iomap_2; 706 goto err_iomap_2;
708 } 707 }
709 708
@@ -714,7 +713,7 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
714 if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2)) 713 if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
715 info->screen_size = memsize1 << 20; 714 info->screen_size = memsize1 << 20;
716 else { 715 else {
717 dev_err(info->dev, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2); 716 dev_err(info->device, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
718 info->screen_size = 16 << 20; 717 info->screen_size = 16 << 20;
719 } 718 }
720 719
@@ -731,19 +730,19 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
731 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); 730 rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
732 if (! ((rc == 1) || (rc == 2))) { 731 if (! ((rc == 1) || (rc == 2))) {
733 rc = -EINVAL; 732 rc = -EINVAL;
734 dev_err(info->dev, "mode %s not found\n", mode_option); 733 dev_err(info->device, "mode %s not found\n", mode_option);
735 goto err_find_mode; 734 goto err_find_mode;
736 } 735 }
737 736
738 rc = fb_alloc_cmap(&info->cmap, 256, 0); 737 rc = fb_alloc_cmap(&info->cmap, 256, 0);
739 if (rc < 0) { 738 if (rc < 0) {
740 dev_err(info->dev, "cannot allocate colormap\n"); 739 dev_err(info->device, "cannot allocate colormap\n");
741 goto err_alloc_cmap; 740 goto err_alloc_cmap;
742 } 741 }
743 742
744 rc = register_framebuffer(info); 743 rc = register_framebuffer(info);
745 if (rc < 0) { 744 if (rc < 0) {
746 dev_err(info->dev, "cannot register framebugger\n"); 745 dev_err(info->device, "cannot register framebugger\n");
747 goto err_reg_fb; 746 goto err_reg_fb;
748 } 747 }
749 748
@@ -817,7 +816,7 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state)
817 struct fb_info *info = pci_get_drvdata(dev); 816 struct fb_info *info = pci_get_drvdata(dev);
818 struct vt8623fb_info *par = info->par; 817 struct vt8623fb_info *par = info->par;
819 818
820 dev_info(info->dev, "suspend\n"); 819 dev_info(info->device, "suspend\n");
821 820
822 acquire_console_sem(); 821 acquire_console_sem();
823 mutex_lock(&(par->open_lock)); 822 mutex_lock(&(par->open_lock));
@@ -848,16 +847,13 @@ static int vt8623_pci_resume(struct pci_dev* dev)
848 struct fb_info *info = pci_get_drvdata(dev); 847 struct fb_info *info = pci_get_drvdata(dev);
849 struct vt8623fb_info *par = info->par; 848 struct vt8623fb_info *par = info->par;
850 849
851 dev_info(info->dev, "resume\n"); 850 dev_info(info->device, "resume\n");
852 851
853 acquire_console_sem(); 852 acquire_console_sem();
854 mutex_lock(&(par->open_lock)); 853 mutex_lock(&(par->open_lock));
855 854
856 if (par->ref_count == 0) { 855 if (par->ref_count == 0)
857 mutex_unlock(&(par->open_lock)); 856 goto fail;
858 release_console_sem();
859 return 0;
860 }
861 857
862 pci_set_power_state(dev, PCI_D0); 858 pci_set_power_state(dev, PCI_D0);
863 pci_restore_state(dev); 859 pci_restore_state(dev);
@@ -870,8 +866,8 @@ static int vt8623_pci_resume(struct pci_dev* dev)
870 vt8623fb_set_par(info); 866 vt8623fb_set_par(info);
871 fb_set_suspend(info, 0); 867 fb_set_suspend(info, 0);
872 868
873 mutex_unlock(&(par->open_lock));
874fail: 869fail:
870 mutex_unlock(&(par->open_lock));
875 release_console_sem(); 871 release_console_sem();
876 872
877 return 0; 873 return 0;
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index 47ed39b52f9c..a463b3dd837b 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -680,11 +680,11 @@ static struct xenbus_driver xenfb = {
680 680
681static int __init xenfb_init(void) 681static int __init xenfb_init(void)
682{ 682{
683 if (!is_running_on_xen()) 683 if (!xen_domain())
684 return -ENODEV; 684 return -ENODEV;
685 685
686 /* Nothing to do if running in dom0. */ 686 /* Nothing to do if running in dom0. */
687 if (is_initial_xendomain()) 687 if (xen_initial_domain())
688 return -ENODEV; 688 return -ENODEV;
689 689
690 return xenbus_register_frontend(&xenfb); 690 return xenbus_register_frontend(&xenfb);
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 7b3a8423f485..5da3d2423cc0 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -24,7 +24,6 @@
24#include <linux/device.h> 24#include <linux/device.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/version.h>
28#include <linux/errno.h> 27#include <linux/errno.h>
29#include <linux/string.h> 28#include <linux/string.h>
30#include <linux/mm.h> 29#include <linux/mm.h>